summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@zip.com.au>2003-08-26 11:49:55 +1000
committerDarren Tucker <dtucker@zip.com.au>2003-08-26 11:49:55 +1000
commit0efd155c3c184f0eaa2e1eb244eaaf066e6906e0 (patch)
tree10f24586373d825d68cefd4a3746fe738cf0614a /sshconnect2.c
parent30912f7259b771a1cf705c0bc47a6c3f3edffb43 (diff)
- markus@cvs.openbsd.org 2003/08/22 10:56:09
[auth2.c auth2-gss.c auth.h compat.c compat.h gss-genr.c gss-serv-krb5.c gss-serv.c monitor.c monitor.h monitor_wrap.c monitor_wrap.h readconf.c readconf.h servconf.c servconf.h session.c session.h ssh-gss.h ssh_config.5 sshconnect2.c sshd_config sshd_config.5] support GSS API user authentication; patches from Simon Wilkinson, stripped down and tested by Jakob and myself.
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c252
1 files changed, 251 insertions, 1 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 6a0bd409a..c71ad506b 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: sshconnect2.c,v 1.120 2003/06/24 08:23:46 markus Exp $"); 26RCSID("$OpenBSD: sshconnect2.c,v 1.121 2003/08/22 10:56:09 markus Exp $");
27 27
28#ifdef KRB5 28#ifdef KRB5
29#include <krb5.h> 29#include <krb5.h>
@@ -57,6 +57,10 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.120 2003/06/24 08:23:46 markus Exp $");
57#include "msg.h" 57#include "msg.h"
58#include "pathnames.h" 58#include "pathnames.h"
59 59
60#ifdef GSSAPI
61#include "ssh-gss.h"
62#endif
63
60/* import */ 64/* import */
61extern char *client_version_string; 65extern char *client_version_string;
62extern char *server_version_string; 66extern char *server_version_string;
@@ -178,6 +182,8 @@ struct Authctxt {
178 Sensitive *sensitive; 182 Sensitive *sensitive;
179 /* kbd-interactive */ 183 /* kbd-interactive */
180 int info_req_seen; 184 int info_req_seen;
185 /* generic */
186 void *methoddata;
181}; 187};
182struct Authmethod { 188struct Authmethod {
183 char *name; /* string to compare against server's list */ 189 char *name; /* string to compare against server's list */
@@ -201,6 +207,15 @@ int userauth_kbdint(Authctxt *);
201int userauth_hostbased(Authctxt *); 207int userauth_hostbased(Authctxt *);
202int userauth_kerberos(Authctxt *); 208int userauth_kerberos(Authctxt *);
203 209
210#ifdef GSSAPI
211int userauth_gssapi(Authctxt *authctxt);
212void input_gssapi_response(int type, u_int32_t, void *);
213void input_gssapi_token(int type, u_int32_t, void *);
214void input_gssapi_hash(int type, u_int32_t, void *);
215void input_gssapi_error(int, u_int32_t, void *);
216void input_gssapi_errtok(int, u_int32_t, void *);
217#endif
218
204void userauth(Authctxt *, char *); 219void userauth(Authctxt *, char *);
205 220
206static int sign_and_send_pubkey(Authctxt *, Identity *); 221static int sign_and_send_pubkey(Authctxt *, Identity *);
@@ -213,6 +228,12 @@ static Authmethod *authmethod_lookup(const char *name);
213static char *authmethods_get(void); 228static char *authmethods_get(void);
214 229
215Authmethod authmethods[] = { 230Authmethod authmethods[] = {
231#ifdef GSSAPI
232 {"gssapi",
233 userauth_gssapi,
234 &options.gss_authentication,
235 NULL},
236#endif
216 {"hostbased", 237 {"hostbased",
217 userauth_hostbased, 238 userauth_hostbased,
218 &options.hostbased_authentication, 239 &options.hostbased_authentication,
@@ -283,6 +304,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
283 authctxt.success = 0; 304 authctxt.success = 0;
284 authctxt.method = authmethod_lookup("none"); 305 authctxt.method = authmethod_lookup("none");
285 authctxt.authlist = NULL; 306 authctxt.authlist = NULL;
307 authctxt.methoddata = NULL;
286 authctxt.sensitive = sensitive; 308 authctxt.sensitive = sensitive;
287 authctxt.info_req_seen = 0; 309 authctxt.info_req_seen = 0;
288 if (authctxt.method == NULL) 310 if (authctxt.method == NULL)
@@ -306,6 +328,10 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
306void 328void
307userauth(Authctxt *authctxt, char *authlist) 329userauth(Authctxt *authctxt, char *authlist)
308{ 330{
331 if (authctxt->methoddata) {
332 xfree(authctxt->methoddata);
333 authctxt->methoddata = NULL;
334 }
309 if (authlist == NULL) { 335 if (authlist == NULL) {
310 authlist = authctxt->authlist; 336 authlist = authctxt->authlist;
311 } else { 337 } else {
@@ -361,6 +387,8 @@ input_userauth_success(int type, u_int32_t seq, void *ctxt)
361 fatal("input_userauth_success: no authentication context"); 387 fatal("input_userauth_success: no authentication context");
362 if (authctxt->authlist) 388 if (authctxt->authlist)
363 xfree(authctxt->authlist); 389 xfree(authctxt->authlist);
390 if (authctxt->methoddata)
391 xfree(authctxt->methoddata);
364 authctxt->success = 1; /* break out */ 392 authctxt->success = 1; /* break out */
365} 393}
366 394
@@ -449,6 +477,228 @@ done:
449 userauth(authctxt, NULL); 477 userauth(authctxt, NULL);
450} 478}
451 479
480#ifdef GSSAPI
481int
482userauth_gssapi(Authctxt *authctxt)
483{
484 Gssctxt *gssctxt = NULL;
485 static gss_OID_set supported = NULL;
486 static int mech = 0;
487 OM_uint32 min;
488 int ok = 0;
489
490 /* Try one GSSAPI method at a time, rather than sending them all at
491 * once. */
492
493 if (supported == NULL)
494 gss_indicate_mechs(&min, &supported);
495
496 /* Check to see if the mechanism is usable before we offer it */
497 while (mech<supported->count && !ok) {
498 if (gssctxt)
499 ssh_gssapi_delete_ctx(&gssctxt);
500 ssh_gssapi_build_ctx(&gssctxt);
501 ssh_gssapi_set_oid(gssctxt, &supported->elements[mech]);
502
503 /* My DER encoding requires length<128 */
504 if (supported->elements[mech].length < 128 &&
505 !GSS_ERROR(ssh_gssapi_import_name(gssctxt,
506 authctxt->host))) {
507 ok = 1; /* Mechanism works */
508 } else {
509 mech++;
510 }
511 }
512
513 if (!ok) return 0;
514
515 authctxt->methoddata=(void *)gssctxt;
516
517 packet_start(SSH2_MSG_USERAUTH_REQUEST);
518 packet_put_cstring(authctxt->server_user);
519 packet_put_cstring(authctxt->service);
520 packet_put_cstring(authctxt->method->name);
521
522 packet_put_int(1);
523
524 /* Some servers encode the OID incorrectly (as we used to) */
525 if (datafellows & SSH_BUG_GSSAPI_BER) {
526 packet_put_string(supported->elements[mech].elements,
527 supported->elements[mech].length);
528 } else {
529 packet_put_int((supported->elements[mech].length)+2);
530 packet_put_char(SSH_GSS_OIDTYPE);
531 packet_put_char(supported->elements[mech].length);
532 packet_put_raw(supported->elements[mech].elements,
533 supported->elements[mech].length);
534 }
535
536 packet_send();
537
538 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response);
539 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
540 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error);
541 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
542
543 mech++; /* Move along to next candidate */
544
545 return 1;
546}
547
548void
549input_gssapi_response(int type, u_int32_t plen, void *ctxt)
550{
551 Authctxt *authctxt = ctxt;
552 Gssctxt *gssctxt;
553 OM_uint32 status, ms;
554 int oidlen;
555 char *oidv;
556 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
557
558 if (authctxt == NULL)
559 fatal("input_gssapi_response: no authentication context");
560 gssctxt = authctxt->methoddata;
561
562 /* Setup our OID */
563 oidv = packet_get_string(&oidlen);
564
565 if (datafellows & SSH_BUG_GSSAPI_BER) {
566 if (!ssh_gssapi_check_oid(gssctxt, oidv, oidlen))
567 fatal("Server returned different OID than expected");
568 } else {
569 if(oidv[0] != SSH_GSS_OIDTYPE || oidv[1] != oidlen-2) {
570 debug("Badly encoded mechanism OID received");
571 userauth(authctxt, NULL);
572 xfree(oidv);
573 return;
574 }
575 if (!ssh_gssapi_check_oid(gssctxt, oidv+2, oidlen-2))
576 fatal("Server returned different OID than expected");
577 }
578
579 packet_check_eom();
580
581 xfree(oidv);
582
583 status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
584 GSS_C_NO_BUFFER, &send_tok, NULL);
585 if (GSS_ERROR(status)) {
586 if (send_tok.length > 0) {
587 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
588 packet_put_string(send_tok.value, send_tok.length);
589 packet_send();
590 gss_release_buffer(&ms, &send_tok);
591 }
592 /* Start again with next method on list */
593 debug("Trying to start again");
594 userauth(authctxt, NULL);
595 return;
596 }
597
598 /* We must have data to send */
599 packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
600 packet_put_string(send_tok.value, send_tok.length);
601 packet_send();
602 gss_release_buffer(&ms, &send_tok);
603}
604
605void
606input_gssapi_token(int type, u_int32_t plen, void *ctxt)
607{
608 Authctxt *authctxt = ctxt;
609 Gssctxt *gssctxt;
610 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
611 gss_buffer_desc recv_tok;
612 OM_uint32 status, ms;
613 u_int slen;
614
615 if (authctxt == NULL)
616 fatal("input_gssapi_response: no authentication context");
617 gssctxt = authctxt->methoddata;
618
619 recv_tok.value = packet_get_string(&slen);
620 recv_tok.length = slen; /* safe typecast */
621
622 packet_check_eom();
623
624 status=ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
625 &recv_tok, &send_tok, NULL);
626
627 xfree(recv_tok.value);
628
629 if (GSS_ERROR(status)) {
630 if (send_tok.length > 0) {
631 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
632 packet_put_string(send_tok.value, send_tok.length);
633 packet_send();
634 gss_release_buffer(&ms, &send_tok);
635 }
636 /* Start again with the next method in the list */
637 userauth(authctxt, NULL);
638 return;
639 }
640
641 if (send_tok.length > 0) {
642 packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
643 packet_put_string(send_tok.value, send_tok.length);
644 packet_send();
645 gss_release_buffer(&ms, &send_tok);
646 }
647
648 if (status == GSS_S_COMPLETE) {
649 /* If that succeeded, send a exchange complete message */
650 packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
651 packet_send();
652 }
653}
654
655void
656input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
657{
658 Authctxt *authctxt = ctxt;
659 Gssctxt *gssctxt;
660 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
661 gss_buffer_desc recv_tok;
662 OM_uint32 status, ms;
663
664 if (authctxt == NULL)
665 fatal("input_gssapi_response: no authentication context");
666 gssctxt = authctxt->methoddata;
667
668 recv_tok.value = packet_get_string(&recv_tok.length);
669
670 packet_check_eom();
671
672 /* Stick it into GSSAPI and see what it says */
673 status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
674 &recv_tok, &send_tok, NULL);
675
676 xfree(recv_tok.value);
677 gss_release_buffer(&ms, &send_tok);
678
679 /* Server will be returning a failed packet after this one */
680}
681
682void
683input_gssapi_error(int type, u_int32_t plen, void *ctxt)
684{
685 OM_uint32 maj, min;
686 char *msg;
687 char *lang;
688
689 maj=packet_get_int();
690 min=packet_get_int();
691 msg=packet_get_string(NULL);
692 lang=packet_get_string(NULL);
693
694 packet_check_eom();
695
696 debug("Server GSSAPI Error:\n%s\n", msg);
697 xfree(msg);
698 xfree(lang);
699}
700#endif /* GSSAPI */
701
452int 702int
453userauth_none(Authctxt *authctxt) 703userauth_none(Authctxt *authctxt)
454{ 704{