auth-client-request.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /* Copyright (c) 2003-2017 Dovecot authors, see the included COPYING file */
  2. #include "lib.h"
  3. #include "str.h"
  4. #include "strescape.h"
  5. #include "ostream.h"
  6. #include "auth-client-private.h"
  7. #include "auth-server-connection.h"
  8. #include "auth-client-request.h"
  9. struct auth_client_request {
  10. pool_t pool;
  11. struct auth_server_connection *conn;
  12. unsigned int id;
  13. time_t created;
  14. struct auth_request_info request_info;
  15. auth_request_callback_t *callback;
  16. void *context;
  17. };
  18. static void auth_server_send_new_request(struct auth_server_connection *conn,
  19. struct auth_client_request *request)
  20. {
  21. struct auth_request_info *info = &request->request_info;
  22. string_t *str;
  23. str = t_str_new(512);
  24. str_printfa(str, "AUTH\t%u\t", request->id);
  25. str_append_tabescaped(str, info->mech);
  26. str_append(str, "\tservice=");
  27. str_append_tabescaped(str, info->service);
  28. if ((info->flags & AUTH_REQUEST_FLAG_SUPPORT_FINAL_RESP) != 0)
  29. str_append(str, "\tfinal-resp-ok");
  30. if ((info->flags & AUTH_REQUEST_FLAG_SECURED) != 0)
  31. str_append(str, "\tsecured");
  32. if ((info->flags & AUTH_REQUEST_FLAG_NO_PENALTY) != 0)
  33. str_append(str, "\tno-penalty");
  34. if ((info->flags & AUTH_REQUEST_FLAG_VALID_CLIENT_CERT) != 0)
  35. str_append(str, "\tvalid-client-cert");
  36. if ((info->flags & AUTH_REQUEST_FLAG_DEBUG) != 0)
  37. str_append(str, "\tdebug");
  38. if (info->session_id != NULL) {
  39. str_append(str, "\tsession=");
  40. str_append_tabescaped(str, info->session_id);
  41. }
  42. if (info->cert_username != NULL) {
  43. str_append(str, "\tcert_username=");
  44. str_append_tabescaped(str, info->cert_username);
  45. }
  46. if (info->local_ip.family != 0)
  47. str_printfa(str, "\tlip=%s", net_ip2addr(&info->local_ip));
  48. if (info->remote_ip.family != 0)
  49. str_printfa(str, "\trip=%s", net_ip2addr(&info->remote_ip));
  50. if (info->local_port != 0)
  51. str_printfa(str, "\tlport=%u", info->local_port);
  52. if (info->remote_port != 0)
  53. str_printfa(str, "\trport=%u", info->remote_port);
  54. /* send the real_* variants only when they differ from the unreal
  55. ones */
  56. if (info->real_local_ip.family != 0 &&
  57. !net_ip_compare(&info->real_local_ip, &info->local_ip)) {
  58. str_printfa(str, "\treal_lip=%s",
  59. net_ip2addr(&info->real_local_ip));
  60. }
  61. if (info->real_remote_ip.family != 0 &&
  62. !net_ip_compare(&info->real_remote_ip, &info->remote_ip)) {
  63. str_printfa(str, "\treal_rip=%s",
  64. net_ip2addr(&info->real_remote_ip));
  65. }
  66. if (info->real_local_port != 0 &&
  67. info->real_local_port != info->local_port)
  68. str_printfa(str, "\treal_lport=%u", info->real_local_port);
  69. if (info->real_remote_port != 0 &&
  70. info->real_remote_port != info->remote_port)
  71. str_printfa(str, "\treal_rport=%u", info->real_remote_port);
  72. if (info->local_name != NULL &&
  73. *info->local_name != '\0') {
  74. str_append(str, "\tlocal_name=");
  75. str_append_tabescaped(str, info->local_name);
  76. }
  77. if (info->client_id != NULL &&
  78. *info->client_id != '\0') {
  79. str_append(str, "\tclient_id=");
  80. str_append_tabescaped(str, info->client_id);
  81. }
  82. if (info->forward_fields != NULL &&
  83. *info->forward_fields != '\0') {
  84. str_append(str, "\tforward_fields=");
  85. str_append_tabescaped(str, info->forward_fields);
  86. }
  87. if (info->initial_resp_base64 != NULL) {
  88. str_append(str, "\tresp=");
  89. str_append_tabescaped(str, info->initial_resp_base64);
  90. }
  91. str_append_c(str, '\n');
  92. if (o_stream_send(conn->output, str_data(str), str_len(str)) < 0)
  93. i_error("Error sending request to auth server: %m");
  94. }
  95. struct auth_client_request *
  96. auth_client_request_new(struct auth_client *client,
  97. const struct auth_request_info *request_info,
  98. auth_request_callback_t *callback, void *context)
  99. {
  100. struct auth_client_request *request;
  101. pool_t pool;
  102. pool = pool_alloconly_create("auth client request", 512);
  103. request = p_new(pool, struct auth_client_request, 1);
  104. request->pool = pool;
  105. request->conn = client->conn;
  106. request->request_info = *request_info;
  107. request->request_info.mech = p_strdup(pool, request_info->mech);
  108. request->request_info.service = p_strdup(pool, request_info->service);
  109. request->request_info.session_id =
  110. p_strdup_empty(pool, request_info->session_id);
  111. request->request_info.cert_username =
  112. p_strdup_empty(pool, request_info->cert_username);
  113. request->request_info.initial_resp_base64 =
  114. p_strdup_empty(pool, request_info->initial_resp_base64);
  115. request->callback = callback;
  116. request->context = context;
  117. request->id =
  118. auth_server_connection_add_request(request->conn, request);
  119. request->created = ioloop_time;
  120. T_BEGIN {
  121. auth_server_send_new_request(request->conn, request);
  122. } T_END;
  123. return request;
  124. }
  125. void auth_client_request_continue(struct auth_client_request *request,
  126. const char *data_base64)
  127. {
  128. struct const_iovec iov[3];
  129. const char *prefix;
  130. prefix = t_strdup_printf("CONT\t%u\t", request->id);
  131. iov[0].iov_base = prefix;
  132. iov[0].iov_len = strlen(prefix);
  133. iov[1].iov_base = data_base64;
  134. iov[1].iov_len = strlen(data_base64);
  135. iov[2].iov_base = "\n";
  136. iov[2].iov_len = 1;
  137. if (o_stream_sendv(request->conn->output, iov, 3) < 0)
  138. i_error("Error sending continue request to auth server: %m");
  139. }
  140. static void ATTR_NULL(3, 4)
  141. call_callback(struct auth_client_request *request,
  142. enum auth_request_status status,
  143. const char *data_base64,
  144. const char *const *args)
  145. {
  146. auth_request_callback_t *callback = request->callback;
  147. if (status != AUTH_REQUEST_STATUS_CONTINUE)
  148. request->callback = NULL;
  149. callback(request, status, data_base64, args, request->context);
  150. }
  151. void auth_client_request_abort(struct auth_client_request **_request)
  152. {
  153. struct auth_client_request *request = *_request;
  154. *_request = NULL;
  155. auth_client_send_cancel(request->conn->client, request->id);
  156. call_callback(request, AUTH_REQUEST_STATUS_ABORT, NULL, NULL);
  157. auth_server_connection_remove_request(request->conn, request->id);
  158. pool_unref(&request->pool);
  159. }
  160. unsigned int auth_client_request_get_id(struct auth_client_request *request)
  161. {
  162. return request->id;
  163. }
  164. unsigned int
  165. auth_client_request_get_server_pid(struct auth_client_request *request)
  166. {
  167. return request->conn->server_pid;
  168. }
  169. const char *auth_client_request_get_cookie(struct auth_client_request *request)
  170. {
  171. return request->conn->cookie;
  172. }
  173. bool auth_client_request_is_aborted(struct auth_client_request *request)
  174. {
  175. return request->callback == NULL;
  176. }
  177. time_t auth_client_request_get_create_time(struct auth_client_request *request)
  178. {
  179. return request->created;
  180. }
  181. void auth_client_request_server_input(struct auth_client_request *request,
  182. enum auth_request_status status,
  183. const char *const *args)
  184. {
  185. const char *const *tmp, *base64_data = NULL;
  186. if (request->callback == NULL) {
  187. /* aborted already */
  188. return;
  189. }
  190. switch (status) {
  191. case AUTH_REQUEST_STATUS_OK:
  192. for (tmp = args; *tmp != NULL; tmp++) {
  193. if (strncmp(*tmp, "resp=", 5) == 0) {
  194. base64_data = *tmp + 5;
  195. break;
  196. }
  197. }
  198. break;
  199. case AUTH_REQUEST_STATUS_CONTINUE:
  200. base64_data = args[0];
  201. args = NULL;
  202. break;
  203. case AUTH_REQUEST_STATUS_FAIL:
  204. case AUTH_REQUEST_STATUS_INTERNAL_FAIL:
  205. case AUTH_REQUEST_STATUS_ABORT:
  206. break;
  207. }
  208. call_callback(request, status, base64_data, args);
  209. if (status != AUTH_REQUEST_STATUS_CONTINUE)
  210. pool_unref(&request->pool);
  211. }
  212. void auth_client_send_cancel(struct auth_client *client, unsigned int id)
  213. {
  214. const char *str = t_strdup_printf("CANCEL\t%u\n", id);
  215. if (o_stream_send_str(client->conn->output, str) < 0)
  216. i_error("Error sending request to auth server: %m");
  217. }