1
0

sshgssc.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #include "putty.h"
  2. #include <string.h>
  3. #include "sshgssc.h"
  4. #include "misc.h"
  5. #ifndef NO_GSSAPI
  6. static Ssh_gss_stat ssh_gssapi_indicate_mech(struct ssh_gss_library *lib,
  7. Ssh_gss_buf *mech)
  8. {
  9. /* Copy constant into mech */
  10. mech->length = GSS_MECH_KRB5->length;
  11. mech->value = GSS_MECH_KRB5->elements;
  12. return SSH_GSS_OK;
  13. }
  14. static Ssh_gss_stat ssh_gssapi_import_name(struct ssh_gss_library *lib,
  15. char *host,
  16. Ssh_gss_name *srv_name)
  17. {
  18. struct gssapi_functions *gss = &lib->u.gssapi;
  19. OM_uint32 min_stat,maj_stat;
  20. gss_buffer_desc host_buf;
  21. char *pStr;
  22. pStr = dupcat("host@", host, NULL);
  23. host_buf.value = pStr;
  24. host_buf.length = strlen(pStr);
  25. maj_stat = gss->import_name(&min_stat, &host_buf,
  26. GSS_C_NT_HOSTBASED_SERVICE, srv_name);
  27. /* Release buffer */
  28. sfree(pStr);
  29. if (maj_stat == GSS_S_COMPLETE) return SSH_GSS_OK;
  30. return SSH_GSS_FAILURE;
  31. }
  32. static Ssh_gss_stat ssh_gssapi_acquire_cred(struct ssh_gss_library *lib,
  33. Ssh_gss_ctx *ctx)
  34. {
  35. gssapi_ssh_gss_ctx *gssctx = snew(gssapi_ssh_gss_ctx);
  36. gssctx->maj_stat = gssctx->min_stat = GSS_S_COMPLETE;
  37. gssctx->ctx = GSS_C_NO_CONTEXT;
  38. *ctx = (Ssh_gss_ctx) gssctx;
  39. return SSH_GSS_OK;
  40. }
  41. static Ssh_gss_stat ssh_gssapi_init_sec_context(struct ssh_gss_library *lib,
  42. Ssh_gss_ctx *ctx,
  43. Ssh_gss_name srv_name,
  44. int to_deleg,
  45. Ssh_gss_buf *recv_tok,
  46. Ssh_gss_buf *send_tok)
  47. {
  48. struct gssapi_functions *gss = &lib->u.gssapi;
  49. gssapi_ssh_gss_ctx *gssctx = (gssapi_ssh_gss_ctx*) *ctx;
  50. OM_uint32 ret_flags;
  51. if (to_deleg) to_deleg = GSS_C_DELEG_FLAG;
  52. gssctx->maj_stat = gss->init_sec_context(&gssctx->min_stat,
  53. GSS_C_NO_CREDENTIAL,
  54. &gssctx->ctx,
  55. srv_name,
  56. (gss_OID) GSS_MECH_KRB5,
  57. GSS_C_MUTUAL_FLAG |
  58. GSS_C_INTEG_FLAG | to_deleg,
  59. 0,
  60. GSS_C_NO_CHANNEL_BINDINGS,
  61. recv_tok,
  62. NULL, /* ignore mech type */
  63. send_tok,
  64. &ret_flags,
  65. NULL); /* ignore time_rec */
  66. if (gssctx->maj_stat == GSS_S_COMPLETE) return SSH_GSS_S_COMPLETE;
  67. if (gssctx->maj_stat == GSS_S_CONTINUE_NEEDED) return SSH_GSS_S_CONTINUE_NEEDED;
  68. return SSH_GSS_FAILURE;
  69. }
  70. static Ssh_gss_stat ssh_gssapi_display_status(struct ssh_gss_library *lib,
  71. Ssh_gss_ctx ctx,
  72. Ssh_gss_buf *buf)
  73. {
  74. struct gssapi_functions *gss = &lib->u.gssapi;
  75. gssapi_ssh_gss_ctx *gssctx = (gssapi_ssh_gss_ctx *) ctx;
  76. OM_uint32 lmin,lmax;
  77. OM_uint32 ccc;
  78. gss_buffer_desc msg_maj=GSS_C_EMPTY_BUFFER;
  79. gss_buffer_desc msg_min=GSS_C_EMPTY_BUFFER;
  80. /* Return empty buffer in case of failure */
  81. SSH_GSS_CLEAR_BUF(buf);
  82. /* get first mesg from GSS */
  83. ccc=0;
  84. lmax=gss->display_status(&lmin,gssctx->maj_stat,GSS_C_GSS_CODE,(gss_OID) GSS_MECH_KRB5,&ccc,&msg_maj);
  85. if (lmax != GSS_S_COMPLETE) return SSH_GSS_FAILURE;
  86. /* get first mesg from Kerberos */
  87. ccc=0;
  88. lmax=gss->display_status(&lmin,gssctx->min_stat,GSS_C_MECH_CODE,(gss_OID) GSS_MECH_KRB5,&ccc,&msg_min);
  89. if (lmax != GSS_S_COMPLETE) {
  90. gss->release_buffer(&lmin, &msg_maj);
  91. return SSH_GSS_FAILURE;
  92. }
  93. /* copy data into buffer */
  94. buf->length = msg_maj.length + msg_min.length + 1;
  95. buf->value = snewn(buf->length + 1, char);
  96. /* copy mem */
  97. memcpy((char *)buf->value, msg_maj.value, msg_maj.length);
  98. ((char *)buf->value)[msg_maj.length] = ' ';
  99. memcpy((char *)buf->value + msg_maj.length + 1, msg_min.value, msg_min.length);
  100. ((char *)buf->value)[buf->length] = 0;
  101. /* free mem & exit */
  102. gss->release_buffer(&lmin, &msg_maj);
  103. gss->release_buffer(&lmin, &msg_min);
  104. return SSH_GSS_OK;
  105. }
  106. static Ssh_gss_stat ssh_gssapi_free_tok(struct ssh_gss_library *lib,
  107. Ssh_gss_buf *send_tok)
  108. {
  109. struct gssapi_functions *gss = &lib->u.gssapi;
  110. OM_uint32 min_stat,maj_stat;
  111. maj_stat = gss->release_buffer(&min_stat, send_tok);
  112. if (maj_stat == GSS_S_COMPLETE) return SSH_GSS_OK;
  113. return SSH_GSS_FAILURE;
  114. }
  115. static Ssh_gss_stat ssh_gssapi_release_cred(struct ssh_gss_library *lib,
  116. Ssh_gss_ctx *ctx)
  117. {
  118. struct gssapi_functions *gss = &lib->u.gssapi;
  119. gssapi_ssh_gss_ctx *gssctx = (gssapi_ssh_gss_ctx *) *ctx;
  120. OM_uint32 min_stat;
  121. OM_uint32 maj_stat=GSS_S_COMPLETE;
  122. if (gssctx == NULL) return SSH_GSS_FAILURE;
  123. if (gssctx->ctx != GSS_C_NO_CONTEXT)
  124. maj_stat = gss->delete_sec_context(&min_stat,&gssctx->ctx,GSS_C_NO_BUFFER);
  125. sfree(gssctx);
  126. if (maj_stat == GSS_S_COMPLETE) return SSH_GSS_OK;
  127. return SSH_GSS_FAILURE;
  128. }
  129. static Ssh_gss_stat ssh_gssapi_release_name(struct ssh_gss_library *lib,
  130. Ssh_gss_name *srv_name)
  131. {
  132. struct gssapi_functions *gss = &lib->u.gssapi;
  133. OM_uint32 min_stat,maj_stat;
  134. maj_stat = gss->release_name(&min_stat, srv_name);
  135. if (maj_stat == GSS_S_COMPLETE) return SSH_GSS_OK;
  136. return SSH_GSS_FAILURE;
  137. }
  138. static Ssh_gss_stat ssh_gssapi_get_mic(struct ssh_gss_library *lib,
  139. Ssh_gss_ctx ctx, Ssh_gss_buf *buf,
  140. Ssh_gss_buf *hash)
  141. {
  142. struct gssapi_functions *gss = &lib->u.gssapi;
  143. gssapi_ssh_gss_ctx *gssctx = (gssapi_ssh_gss_ctx *) ctx;
  144. if (gssctx == NULL) return SSH_GSS_FAILURE;
  145. return gss->get_mic(&(gssctx->min_stat), gssctx->ctx, 0, buf, hash);
  146. }
  147. static Ssh_gss_stat ssh_gssapi_free_mic(struct ssh_gss_library *lib,
  148. Ssh_gss_buf *hash)
  149. {
  150. /* On Unix this is the same freeing process as ssh_gssapi_free_tok. */
  151. return ssh_gssapi_free_tok(lib, hash);
  152. }
  153. void ssh_gssapi_bind_fns(struct ssh_gss_library *lib)
  154. {
  155. lib->indicate_mech = ssh_gssapi_indicate_mech;
  156. lib->import_name = ssh_gssapi_import_name;
  157. lib->release_name = ssh_gssapi_release_name;
  158. lib->init_sec_context = ssh_gssapi_init_sec_context;
  159. lib->free_tok = ssh_gssapi_free_tok;
  160. lib->acquire_cred = ssh_gssapi_acquire_cred;
  161. lib->release_cred = ssh_gssapi_release_cred;
  162. lib->get_mic = ssh_gssapi_get_mic;
  163. lib->free_mic = ssh_gssapi_free_mic;
  164. lib->display_status = ssh_gssapi_display_status;
  165. }
  166. #else
  167. /* Dummy function so this source file defines something if NO_GSSAPI
  168. is defined. */
  169. int ssh_gssapi_init(void)
  170. {
  171. return 0;
  172. }
  173. #endif