X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/5ba55adaa243d18f3474fd9f9015b50fc58421a8..cc365543c473fc49be6e02687ce43d16ef918e67:/auth2-chall.c diff --git a/auth2-chall.c b/auth2-chall.c index ad4f7ac4..e6dbffe2 100644 --- a/auth2-chall.c +++ b/auth2-chall.c @@ -1,3 +1,4 @@ +/* $OpenBSD: auth2-chall.c,v 1.34 2008/12/09 04:32:22 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Per Allansson. All rights reserved. @@ -22,24 +23,39 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include "includes.h" -RCSID("$OpenBSD: auth2-chall.c,v 1.5 2001/05/18 14:13:28 markus Exp $"); +#include + +#include +#include +#include + +#include "xmalloc.h" #include "ssh2.h" +#include "key.h" +#include "hostfile.h" #include "auth.h" +#include "buffer.h" #include "packet.h" -#include "xmalloc.h" #include "dispatch.h" -#include "auth.h" #include "log.h" +#include "servconf.h" + +/* import */ +extern ServerOptions options; -static int auth2_challenge_start(Authctxt *authctxt); -static int send_userauth_info_request(Authctxt *authctxt); -static void input_userauth_info_response(int type, int plen, void *ctxt); +static int auth2_challenge_start(Authctxt *); +static int send_userauth_info_request(Authctxt *); +static void input_userauth_info_response(int, u_int32_t, void *); #ifdef BSD_AUTH extern KbdintDevice bsdauth_device; #else +#ifdef USE_PAM +extern KbdintDevice sshpam_device; +#endif #ifdef SKEY extern KbdintDevice skey_device; #endif @@ -49,6 +65,9 @@ KbdintDevice *devices[] = { #ifdef BSD_AUTH &bsdauth_device, #else +#ifdef USE_PAM + &sshpam_device, +#endif #ifdef SKEY &skey_device, #endif @@ -62,34 +81,59 @@ struct KbdintAuthctxt char *devices; void *ctxt; KbdintDevice *device; + u_int nreq; }; -KbdintAuthctxt * +#ifdef USE_PAM +void +remove_kbdint_device(const char *devname) +{ + int i, j; + + for (i = 0; devices[i] != NULL; i++) + if (strcmp(devices[i]->name, devname) == 0) { + for (j = i; devices[j] != NULL; j++) + devices[j] = devices[j+1]; + i--; + } +} +#endif + +static KbdintAuthctxt * kbdint_alloc(const char *devs) { KbdintAuthctxt *kbdintctxt; + Buffer b; int i; - char buf[1024]; + +#ifdef USE_PAM + if (!options.use_pam) + remove_kbdint_device("pam"); +#endif kbdintctxt = xmalloc(sizeof(KbdintAuthctxt)); if (strcmp(devs, "") == 0) { - buf[0] = '\0'; + buffer_init(&b); for (i = 0; devices[i]; i++) { - if (i != 0) - strlcat(buf, ",", sizeof(buf)); - strlcat(buf, devices[i]->name, sizeof(buf)); + if (buffer_len(&b) > 0) + buffer_append(&b, ",", 1); + buffer_append(&b, devices[i]->name, + strlen(devices[i]->name)); } - debug("kbdint_alloc: devices '%s'", buf); - kbdintctxt->devices = xstrdup(buf); + buffer_append(&b, "\0", 1); + kbdintctxt->devices = xstrdup(buffer_ptr(&b)); + buffer_free(&b); } else { kbdintctxt->devices = xstrdup(devs); } + debug("kbdint_alloc: devices '%s'", kbdintctxt->devices); kbdintctxt->ctxt = NULL; kbdintctxt->device = NULL; + kbdintctxt->nreq = 0; return kbdintctxt; } -void +static void kbdint_reset_device(KbdintAuthctxt *kbdintctxt) { if (kbdintctxt->ctxt) { @@ -98,7 +142,7 @@ kbdint_reset_device(KbdintAuthctxt *kbdintctxt) } kbdintctxt->device = NULL; } -void +static void kbdint_free(KbdintAuthctxt *kbdintctxt) { if (kbdintctxt->device) @@ -110,7 +154,7 @@ kbdint_free(KbdintAuthctxt *kbdintctxt) xfree(kbdintctxt); } /* get next device */ -int +static int kbdint_next_device(KbdintAuthctxt *kbdintctxt) { size_t len; @@ -132,14 +176,14 @@ kbdint_next_device(KbdintAuthctxt *kbdintctxt) kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL; xfree(t); debug2("kbdint_next_device: devices %s", kbdintctxt->devices ? - kbdintctxt->devices : ""); + kbdintctxt->devices : ""); } while (kbdintctxt->devices && !kbdintctxt->device); return kbdintctxt->device ? 1 : 0; } /* - * try challenge-reponse, set authctxt->postponed if we have to + * try challenge-response, set authctxt->postponed if we have to * wait for the response. */ int @@ -149,13 +193,25 @@ auth2_challenge(Authctxt *authctxt, char *devs) authctxt->user ? authctxt->user : "", devs ? devs : ""); - if (!authctxt->valid || authctxt->user == NULL || !devs) + if (authctxt->user == NULL || !devs) return 0; - if (authctxt->kbdintctxt == NULL) + if (authctxt->kbdintctxt == NULL) authctxt->kbdintctxt = kbdint_alloc(devs); return auth2_challenge_start(authctxt); } +/* unregister kbd-int callbacks and context */ +void +auth2_challenge_stop(Authctxt *authctxt) +{ + /* unregister callback */ + dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); + if (authctxt->kbdintctxt != NULL) { + kbdint_free(authctxt->kbdintctxt); + authctxt->kbdintctxt = NULL; + } +} + /* side effect: sets authctxt->postponed if a reply was sent*/ static int auth2_challenge_start(Authctxt *authctxt) @@ -166,21 +222,18 @@ auth2_challenge_start(Authctxt *authctxt) kbdintctxt->devices ? kbdintctxt->devices : ""); if (kbdint_next_device(kbdintctxt) == 0) { - kbdint_free(kbdintctxt); - authctxt->kbdintctxt = NULL; + auth2_challenge_stop(authctxt); return 0; } debug("auth2_challenge_start: trying authentication method '%s'", kbdintctxt->device->name); if ((kbdintctxt->ctxt = kbdintctxt->device->init_ctx(authctxt)) == NULL) { - kbdint_free(kbdintctxt); - authctxt->kbdintctxt = NULL; + auth2_challenge_stop(authctxt); return 0; } if (send_userauth_info_request(authctxt) == 0) { - kbdint_free(kbdintctxt); - authctxt->kbdintctxt = NULL; + auth2_challenge_stop(authctxt); return 0; } dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, @@ -195,27 +248,26 @@ send_userauth_info_request(Authctxt *authctxt) { KbdintAuthctxt *kbdintctxt; char *name, *instr, **prompts; - int i; - u_int numprompts, *echo_on; + u_int i, *echo_on; kbdintctxt = authctxt->kbdintctxt; if (kbdintctxt->device->query(kbdintctxt->ctxt, - &name, &instr, &numprompts, &prompts, &echo_on)) + &name, &instr, &kbdintctxt->nreq, &prompts, &echo_on)) return 0; packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST); packet_put_cstring(name); packet_put_cstring(instr); - packet_put_cstring(""); /* language not used */ - packet_put_int(numprompts); - for (i = 0; i < numprompts; i++) { + packet_put_cstring(""); /* language not used */ + packet_put_int(kbdintctxt->nreq); + for (i = 0; i < kbdintctxt->nreq; i++) { packet_put_cstring(prompts[i]); packet_put_char(echo_on[i]); } packet_send(); packet_write_wait(); - for (i = 0; i < numprompts; i++) + for (i = 0; i < kbdintctxt->nreq; i++) xfree(prompts[i]); xfree(prompts); xfree(echo_on); @@ -225,12 +277,12 @@ send_userauth_info_request(Authctxt *authctxt) } static void -input_userauth_info_response(int type, int plen, void *ctxt) +input_userauth_info_response(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; KbdintAuthctxt *kbdintctxt; - int i, authenticated = 0, res, len; - u_int nresp; + int authenticated = 0, res; + u_int i, nresp; char **response = NULL, *method; if (authctxt == NULL) @@ -243,19 +295,18 @@ input_userauth_info_response(int type, int plen, void *ctxt) authctxt->postponed = 0; /* reset */ nresp = packet_get_int(); + if (nresp != kbdintctxt->nreq) + fatal("input_userauth_info_response: wrong number of replies"); + if (nresp > 100) + fatal("input_userauth_info_response: too many replies"); if (nresp > 0) { - response = xmalloc(nresp * sizeof(char*)); + response = xcalloc(nresp, sizeof(char *)); for (i = 0; i < nresp; i++) response[i] = packet_get_string(NULL); } - packet_done(); + packet_check_eom(); - if (authctxt->valid) { - res = kbdintctxt->device->respond(kbdintctxt->ctxt, - nresp, response); - } else { - res = -1; - } + res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response); for (i = 0; i < nresp; i++) { memset(response[i], 'r', strlen(response[i])); @@ -267,35 +318,23 @@ input_userauth_info_response(int type, int plen, void *ctxt) switch (res) { case 0: /* Success! */ - authenticated = 1; + authenticated = authctxt->valid ? 1 : 0; break; case 1: /* Authentication needs further interaction */ - authctxt->postponed = 1; - if (send_userauth_info_request(authctxt) == 0) { - authctxt->postponed = 0; - } + if (send_userauth_info_request(authctxt) == 1) + authctxt->postponed = 1; break; default: /* Failure! */ break; } - len = strlen("keyboard-interactive") + 2 + - strlen(kbdintctxt->device->name); - method = xmalloc(len); - method[0] = '\0'; - strlcat(method, "keyboard-interactive", len); - strlcat(method, "/", len); - strlcat(method, kbdintctxt->device->name, len); + xasprintf(&method, "keyboard-interactive/%s", kbdintctxt->device->name); if (!authctxt->postponed) { - /* unregister callback */ - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); - if (authenticated) { - kbdint_free(kbdintctxt); - authctxt->kbdintctxt = NULL; + auth2_challenge_stop(authctxt); } else { /* start next device */ /* may set authctxt->postponed */ @@ -305,3 +344,31 @@ input_userauth_info_response(int type, int plen, void *ctxt) userauth_finish(authctxt, authenticated, method); xfree(method); } + +void +privsep_challenge_enable(void) +{ +#if defined(BSD_AUTH) || defined(USE_PAM) || defined(SKEY) + int n = 0; +#endif +#ifdef BSD_AUTH + extern KbdintDevice mm_bsdauth_device; +#endif +#ifdef USE_PAM + extern KbdintDevice mm_sshpam_device; +#endif +#ifdef SKEY + extern KbdintDevice mm_skey_device; +#endif + +#ifdef BSD_AUTH + devices[n++] = &mm_bsdauth_device; +#else +#ifdef USE_PAM + devices[n++] = &mm_sshpam_device; +#endif +#ifdef SKEY + devices[n++] = &mm_skey_device; +#endif +#endif +}