/crypto/heimdal/appl/test/gssapi_client.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 273 lines · 202 code · 37 blank · 34 comment · 30 complexity · f5e0ada0de33881e91f98d645a806c65 MD5 · raw file

  1. /*
  2. * Copyright (c) 1997 - 2000 Kungliga Tekniska Hรถgskolan
  3. * (Royal Institute of Technology, Stockholm, Sweden).
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. *
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. *
  17. * 3. Neither the name of the Institute nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #include "test_locl.h"
  34. #include <gssapi/gssapi.h>
  35. #include <gssapi/gssapi_krb5.h>
  36. #include <gssapi/gssapi_spnego.h>
  37. #include "gss_common.h"
  38. RCSID("$Id$");
  39. static int
  40. do_trans (int sock, gss_ctx_id_t context_hdl)
  41. {
  42. OM_uint32 maj_stat, min_stat;
  43. gss_buffer_desc real_input_token, real_output_token;
  44. gss_buffer_t input_token = &real_input_token,
  45. output_token = &real_output_token;
  46. /* get_mic */
  47. input_token->length = 3;
  48. input_token->value = strdup("hej");
  49. maj_stat = gss_get_mic(&min_stat,
  50. context_hdl,
  51. GSS_C_QOP_DEFAULT,
  52. input_token,
  53. output_token);
  54. if (GSS_ERROR(maj_stat))
  55. gss_err (1, min_stat, "gss_get_mic");
  56. write_token (sock, input_token);
  57. write_token (sock, output_token);
  58. /* wrap */
  59. input_token->length = 7;
  60. input_token->value = "hemligt";
  61. maj_stat = gss_wrap (&min_stat,
  62. context_hdl,
  63. 0,
  64. GSS_C_QOP_DEFAULT,
  65. input_token,
  66. NULL,
  67. output_token);
  68. if (GSS_ERROR(maj_stat))
  69. gss_err (1, min_stat, "gss_wrap");
  70. write_token (sock, output_token);
  71. maj_stat = gss_wrap (&min_stat,
  72. context_hdl,
  73. 1,
  74. GSS_C_QOP_DEFAULT,
  75. input_token,
  76. NULL,
  77. output_token);
  78. if (GSS_ERROR(maj_stat))
  79. gss_err (1, min_stat, "gss_wrap");
  80. write_token (sock, output_token);
  81. return 0;
  82. }
  83. extern char *password;
  84. static int
  85. proto (int sock, const char *hostname, const char *service)
  86. {
  87. struct sockaddr_storage remote, local;
  88. socklen_t addrlen;
  89. int context_established = 0;
  90. gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
  91. gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
  92. gss_buffer_desc real_input_token, real_output_token;
  93. gss_buffer_t input_token = &real_input_token,
  94. output_token = &real_output_token;
  95. OM_uint32 maj_stat, min_stat;
  96. gss_name_t server;
  97. gss_buffer_desc name_token;
  98. u_char init_buf[4];
  99. u_char acct_buf[4];
  100. gss_OID mech_oid;
  101. char *str;
  102. mech_oid = select_mech(mech);
  103. name_token.length = asprintf (&str,
  104. "%s@%s", service, hostname);
  105. if (str == NULL)
  106. errx(1, "malloc - out of memory");
  107. name_token.value = str;
  108. maj_stat = gss_import_name (&min_stat,
  109. &name_token,
  110. GSS_C_NT_HOSTBASED_SERVICE,
  111. &server);
  112. if (GSS_ERROR(maj_stat))
  113. gss_err (1, min_stat,
  114. "Error importing name `%s@%s':\n", service, hostname);
  115. if (password) {
  116. gss_buffer_desc pw;
  117. pw.value = password;
  118. pw.length = strlen(password);
  119. maj_stat = gss_acquire_cred_with_password(&min_stat,
  120. GSS_C_NO_NAME,
  121. &pw,
  122. GSS_C_INDEFINITE,
  123. GSS_C_NO_OID_SET,
  124. GSS_C_INITIATE,
  125. &cred,
  126. NULL,
  127. NULL);
  128. if (GSS_ERROR(maj_stat))
  129. gss_err (1, min_stat,
  130. "Error acquiring default initiator credentials");
  131. }
  132. addrlen = sizeof(local);
  133. if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
  134. || addrlen > sizeof(local))
  135. err (1, "getsockname(%s)", hostname);
  136. addrlen = sizeof(remote);
  137. if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
  138. || addrlen > sizeof(remote))
  139. err (1, "getpeername(%s)", hostname);
  140. input_token->length = 0;
  141. output_token->length = 0;
  142. #if 0
  143. struct gss_channel_bindings_struct input_chan_bindings;
  144. input_chan_bindings.initiator_addrtype = GSS_C_AF_INET;
  145. input_chan_bindings.initiator_address.length = 4;
  146. init_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF;
  147. init_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF;
  148. init_buf[2] = (local.sin_addr.s_addr >> 8) & 0xFF;
  149. init_buf[3] = (local.sin_addr.s_addr >> 0) & 0xFF;
  150. input_chan_bindings.initiator_address.value = init_buf;
  151. input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET;
  152. input_chan_bindings.acceptor_address.length = 4;
  153. acct_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF;
  154. acct_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF;
  155. acct_buf[2] = (remote.sin_addr.s_addr >> 8) & 0xFF;
  156. acct_buf[3] = (remote.sin_addr.s_addr >> 0) & 0xFF;
  157. input_chan_bindings.acceptor_address.value = acct_buf;
  158. input_chan_bindings.application_data.value = emalloc(4);
  159. * (unsigned short*)input_chan_bindings.application_data.value = local.sin_port;
  160. * ((unsigned short *)input_chan_bindings.application_data.value + 1) = remote.sin_port;
  161. input_chan_bindings.application_data.length = 4;
  162. input_chan_bindings.application_data.length = 0;
  163. input_chan_bindings.application_data.value = NULL;
  164. #endif
  165. while(!context_established) {
  166. maj_stat =
  167. gss_init_sec_context(&min_stat,
  168. cred,
  169. &context_hdl,
  170. server,
  171. mech_oid,
  172. GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
  173. 0,
  174. NULL,
  175. input_token,
  176. NULL,
  177. output_token,
  178. NULL,
  179. NULL);
  180. if (GSS_ERROR(maj_stat))
  181. gss_err (1, min_stat, "gss_init_sec_context");
  182. if (output_token->length != 0)
  183. write_token (sock, output_token);
  184. if (GSS_ERROR(maj_stat)) {
  185. if (context_hdl != GSS_C_NO_CONTEXT)
  186. gss_delete_sec_context (&min_stat,
  187. &context_hdl,
  188. GSS_C_NO_BUFFER);
  189. break;
  190. }
  191. if (maj_stat & GSS_S_CONTINUE_NEEDED) {
  192. read_token (sock, input_token);
  193. } else {
  194. context_established = 1;
  195. }
  196. }
  197. if (fork_flag) {
  198. pid_t pid;
  199. int pipefd[2];
  200. if (pipe (pipefd) < 0)
  201. err (1, "pipe");
  202. pid = fork ();
  203. if (pid < 0)
  204. err (1, "fork");
  205. if (pid != 0) {
  206. gss_buffer_desc buf;
  207. maj_stat = gss_export_sec_context (&min_stat,
  208. &context_hdl,
  209. &buf);
  210. if (GSS_ERROR(maj_stat))
  211. gss_err (1, min_stat, "gss_export_sec_context");
  212. write_token (pipefd[1], &buf);
  213. exit (0);
  214. } else {
  215. gss_ctx_id_t context_hdl;
  216. gss_buffer_desc buf;
  217. close (pipefd[1]);
  218. read_token (pipefd[0], &buf);
  219. close (pipefd[0]);
  220. maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl);
  221. if (GSS_ERROR(maj_stat))
  222. gss_err (1, min_stat, "gss_import_sec_context");
  223. gss_release_buffer (&min_stat, &buf);
  224. return do_trans (sock, context_hdl);
  225. }
  226. } else {
  227. return do_trans (sock, context_hdl);
  228. }
  229. }
  230. int
  231. main(int argc, char **argv)
  232. {
  233. krb5_context context; /* XXX */
  234. int port = client_setup(&context, &argc, argv);
  235. return client_doit (argv[argc], port, service, proto);
  236. }