00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "includes.h"
00028
00029 #ifdef GSSAPI
00030
00031 #include "auth.h"
00032 #include "ssh2.h"
00033 #include "xmalloc.h"
00034 #include "log.h"
00035 #include "dispatch.h"
00036 #include "servconf.h"
00037 #include "packet.h"
00038 #include "monitor_wrap.h"
00039
00040 #include "ssh-gss.h"
00041
00042 extern ServerOptions options;
00043
00044 static void input_gssapi_token(int type, u_int32_t plen, void *ctxt);
00045 static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
00046 static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
00047 static void input_gssapi_errtok(int, u_int32_t, void *);
00048
00049
00050
00051
00052
00053 static int
00054 userauth_gssapi(Authctxt *authctxt)
00055 {
00056 gss_OID_desc goid = {0, NULL};
00057 Gssctxt *ctxt = NULL;
00058 int mechs;
00059 gss_OID_set supported;
00060 int present;
00061 OM_uint32 ms;
00062 u_int len;
00063 u_char *doid = NULL;
00064
00065 if (!authctxt->valid || authctxt->user == NULL)
00066 return (0);
00067
00068 mechs = packet_get_int();
00069 if (mechs == 0) {
00070 debug("Mechanism negotiation is not supported");
00071 return (0);
00072 }
00073
00074 ssh_gssapi_supported_oids(&supported);
00075 do {
00076 mechs--;
00077
00078 if (doid)
00079 xfree(doid);
00080
00081 present = 0;
00082 doid = packet_get_string(&len);
00083
00084 if (len > 2 && doid[0] == SSH_GSS_OIDTYPE &&
00085 doid[1] == len - 2) {
00086 goid.elements = doid + 2;
00087 goid.length = len - 2;
00088 gss_test_oid_set_member(&ms, &goid, supported,
00089 &present);
00090 } else {
00091 logit("Badly formed OID received");
00092 }
00093 } while (mechs > 0 && !present);
00094
00095 gss_release_oid_set(&ms, &supported);
00096
00097 if (!present) {
00098 xfree(doid);
00099 return (0);
00100 }
00101
00102 if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
00103 xfree(doid);
00104 return (0);
00105 }
00106
00107 authctxt->methoddata = (void *)ctxt;
00108
00109 packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE);
00110
00111
00112 packet_put_string(doid, len);
00113
00114 packet_send();
00115 xfree(doid);
00116
00117 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
00118 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
00119 authctxt->postponed = 1;
00120
00121 return (0);
00122 }
00123
00124 static void
00125 input_gssapi_token(int type, u_int32_t plen, void *ctxt)
00126 {
00127 Authctxt *authctxt = ctxt;
00128 Gssctxt *gssctxt;
00129 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
00130 gss_buffer_desc recv_tok;
00131 OM_uint32 maj_status, min_status, flags;
00132 u_int len;
00133
00134 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
00135 fatal("No authentication or GSSAPI context");
00136
00137 gssctxt = authctxt->methoddata;
00138 recv_tok.value = packet_get_string(&len);
00139 recv_tok.length = len;
00140
00141 packet_check_eom();
00142
00143 maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
00144 &send_tok, &flags));
00145
00146 xfree(recv_tok.value);
00147
00148 if (GSS_ERROR(maj_status)) {
00149 if (send_tok.length != 0) {
00150 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
00151 packet_put_string(send_tok.value, send_tok.length);
00152 packet_send();
00153 }
00154 authctxt->postponed = 0;
00155 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
00156 userauth_finish(authctxt, 0, "gssapi-with-mic");
00157 } else {
00158 if (send_tok.length != 0) {
00159 packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
00160 packet_put_string(send_tok.value, send_tok.length);
00161 packet_send();
00162 }
00163 if (maj_status == GSS_S_COMPLETE) {
00164 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
00165 if (flags & GSS_C_INTEG_FLAG)
00166 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC,
00167 &input_gssapi_mic);
00168 else
00169 dispatch_set(
00170 SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
00171 &input_gssapi_exchange_complete);
00172 }
00173 }
00174
00175 gss_release_buffer(&min_status, &send_tok);
00176 }
00177
00178 static void
00179 input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
00180 {
00181 Authctxt *authctxt = ctxt;
00182 Gssctxt *gssctxt;
00183 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
00184 gss_buffer_desc recv_tok;
00185 OM_uint32 maj_status;
00186 u_int len;
00187
00188 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
00189 fatal("No authentication or GSSAPI context");
00190
00191 gssctxt = authctxt->methoddata;
00192 recv_tok.value = packet_get_string(&len);
00193 recv_tok.length = len;
00194
00195 packet_check_eom();
00196
00197
00198 maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
00199 &send_tok, NULL));
00200
00201 xfree(recv_tok.value);
00202
00203
00204 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
00205 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
00206
00207
00208
00209 gss_release_buffer(&maj_status, &send_tok);
00210 }
00211
00212
00213
00214
00215
00216
00217
00218 static void
00219 input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
00220 {
00221 Authctxt *authctxt = ctxt;
00222 Gssctxt *gssctxt;
00223 int authenticated;
00224
00225 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
00226 fatal("No authentication or GSSAPI context");
00227
00228 gssctxt = authctxt->methoddata;
00229
00230
00231
00232
00233
00234
00235 packet_check_eom();
00236
00237 authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
00238
00239 authctxt->postponed = 0;
00240 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
00241 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
00242 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
00243 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
00244 userauth_finish(authctxt, authenticated, "gssapi-with-mic");
00245 }
00246
00247 static void
00248 input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
00249 {
00250 Authctxt *authctxt = ctxt;
00251 Gssctxt *gssctxt;
00252 int authenticated = 0;
00253 Buffer b;
00254 gss_buffer_desc mic, gssbuf;
00255 u_int len;
00256
00257 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
00258 fatal("No authentication or GSSAPI context");
00259
00260 gssctxt = authctxt->methoddata;
00261
00262 mic.value = packet_get_string(&len);
00263 mic.length = len;
00264
00265 ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
00266 "gssapi-with-mic");
00267
00268 gssbuf.value = buffer_ptr(&b);
00269 gssbuf.length = buffer_len(&b);
00270
00271 if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
00272 authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
00273 else
00274 logit("GSSAPI MIC check failed");
00275
00276 buffer_free(&b);
00277 xfree(mic.value);
00278
00279 authctxt->postponed = 0;
00280 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
00281 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
00282 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
00283 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
00284 userauth_finish(authctxt, authenticated, "gssapi-with-mic");
00285 }
00286
00287 Authmethod method_gssapi = {
00288 "gssapi-with-mic",
00289 userauth_gssapi,
00290 &options.gss_authentication
00291 };
00292
00293 #endif