/* This file is in the public domain. */ #include #include #include extern const char *__progname; #include "pp.h" #include "bpp.h" #include "str.h" #include "errf.h" #include "msgs.h" #include "util.h" #include "panic.h" #include "config.h" #include "nested.h" #include "escaped.h" #include "interact.h" #include "userauth.h" #include "pkt-util.h" #include "algs-list.h" typedef struct pwpriv PWPRIV; struct pwpriv { CUASTATE *s; int state; #define PWS_NORM 1 } ; static int uac_pw_canuse(BPP *b __attribute__((__unused__))) { return(!config_bool("no-interaction")); } static unsigned char *do_pw(CUASTATE *s) { unsigned char *opp; char *resp; int resplen; get_with_prompt(&resp,&resplen,GWP_DEV_TTY|GWP_NO_ECHO,"Password: "); opp = (*s->pkthead)(s); *opp++ = 0; opp = put_string(opp,resp,resplen); free(resp); return(opp); } static unsigned char *uac_pw_start(CUASTATE *s) { PWPRIV *p; p = malloc(sizeof(PWPRIV)); s->algpriv = p; p->s = s; p->state = PWS_NORM; return(do_pw(s)); } static int uac_pw_partial(CUASTATE *s __attribute__((__unused__))) { fprintf(errf,"%s: server returned partial success to password auth\n",__progname); exit(1); } static int uac_pw_run(CUASTATE *s) { PWPRIV *p; BPP *b; NESTED void fail(const void *dataptr, const char *fmt, ...) { va_list ap; va_start(ap,fmt); pp_vfail(b,dataptr,fmt,ap); va_end(ap); } b = s->layer->b; p = s->algpriv; switch (b->ipkt[0]) { case SSH_MSG_USERAUTH_PASSWD_CHANGEREQ: printf("Server requires password change, which isn't supported\n"); exit(1); break; default: fprintf(errf,"%s: password authorization error: unexpected message (type %d)\n",__progname,b->ipkt[0]); exit(1); break; } } static int uac_pw_retry(CUASTATE *s) { PWPRIV *p; BPP *b; b = s->layer->b; p = s->algpriv; p->state = PWS_NORM; b->oplen = do_pw(s) - &b->opkt[0]; return(UA_SEND); } static void uac_pw_done(CUASTATE *s) { free(s->algpriv); s->algpriv = 0; } #ifdef NO_SERVER_PW_AUTH static int uas_pw_canuse(SUASTATE *s __attribute__((__unused__))) { return(0); } #else static int uas_pw_canuse(SUASTATE *s) { return(s->layer->b->r_enc!=&encalg_none); } #endif static int uas_pw_request(SUASTATE *s, const void *rest, int restlen) { #ifdef NO_SERVER_PW_AUTH s=s; rest=rest; restlen=restlen; panic("called"); #else __label__ parsefail; int newpwinc; STR pwstr; char *pw; const void *newrest; int newrlen; int rv; NESTED void fail(const void *dp __attribute__((__unused__)), const char *fmt __attribute__((__unused__)), ...) { goto parsefail; } NESTED void clears(void) { free_str(pwstr); free(pw); } if (0) { parsefail:; logmsg(LM_NOTE|LM_PEER,"password extra data parse failure"); send_disconnect(SSH_DISCONNECT_PROTOCOL_ERROR,0,0,0,0); exit(0); } pw = 0; parse_data(rest,restlen,&fail, PP_BOOL(&newpwinc), PP_STRING(&pwstr), PP_REST(&newrest,&newrlen) ); if (newpwinc) { parse_data(newrest,newrlen,&fail,PP_SKIP(PP_STRING(0)),PP_ENDSHERE); send_failure(s,0); clears(); return(0); } else { parse_data(newrest,newrlen,&fail,PP_ENDSHERE); } add_attempt(s); pw = blk_to_cstr(pwstr.data,pwstr.len); if (s->nosuchuser) { crypt(pw,"englebert"); rv = 0; logmsg(LM_NOTE|LM_PEER,"password auth for non-user %s",s->curuser); } else if (config_bool("never-auth")) { crypt(pw,"englebert"); rv = 0; logmsg(LM_NOTE|LM_PEER,"password never-auth for %s",s->curuser); } else { rv = ! strcmp(crypt(pw,s->passwd),s->passwd); if (rv) { logmsg(LM_INFO|LM_PEER,"password auth succeeded for %s",s->curuser); } else { logmsg(LM_NOTE|LM_PEER,"password auth failed for %s",s->curuser); } } if (! rv) send_failure(s,0); return(rv); #endif } UAALG uaalg_password = { "password", 0, { &uac_pw_canuse, &uac_pw_start, &uac_pw_partial, &uac_pw_run, &uac_pw_retry, &uac_pw_done }, { &uas_pw_canuse, &uas_pw_request, 0 } };