void cli_auth_interactive() { TRACE(("enter cli_auth_interactive")) CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); /* username */ buf_putstring(ses.writepayload, cli_opts.username, strlen(cli_opts.username)); /* service name */ buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION, SSH_SERVICE_CONNECTION_LEN); /* method */ buf_putstring(ses.writepayload, AUTH_METHOD_INTERACT, AUTH_METHOD_INTERACT_LEN); /* empty language tag */ buf_putstring(ses.writepayload, "", 0); /* empty submethods */ buf_putstring(ses.writepayload, "", 0); encrypt_packet(); cli_ses.interact_request_received = 0; TRACE(("leave cli_auth_interactive")) }
static void tcp_acceptor(struct Listener *listener, int sock) { int fd; struct sockaddr_storage addr; socklen_t len; char ipstring[NI_MAXHOST], portstring[NI_MAXSERV]; struct TCPListener *tcpinfo = (struct TCPListener*)(listener->typedata); len = sizeof(addr); fd = accept(sock, (struct sockaddr*)&addr, &len); if (fd < 0) { return; } if (getnameinfo((struct sockaddr*)&addr, len, ipstring, sizeof(ipstring), portstring, sizeof(portstring), NI_NUMERICHOST | NI_NUMERICSERV) != 0) { m_close(fd); return; } if (send_msg_channel_open_init(fd, tcpinfo->chantype) == DROPBEAR_SUCCESS) { char* addr = NULL; unsigned int port = 0; if (tcpinfo->tcp_type == direct) { /* "direct-tcpip" */ /* host to connect, port to connect */ addr = tcpinfo->sendaddr; port = tcpinfo->sendport; } else { dropbear_assert(tcpinfo->tcp_type == forwarded); /* "forwarded-tcpip" */ /* address that was connected, port that was connected */ addr = tcpinfo->request_listenaddr; port = tcpinfo->listenport; } if (addr == NULL) { addr = "localhost"; } buf_putstring(ses.writepayload, addr, strlen(addr)); buf_putint(ses.writepayload, port); /* originator ip */ buf_putstring(ses.writepayload, ipstring, strlen(ipstring)); /* originator port */ buf_putint(ses.writepayload, atol(portstring)); encrypt_packet(); } else { /* XXX debug? */ close(fd); } }
/* Send our list of algorithms we can use */ void send_msg_kexinit() { CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_KEXINIT); /* cookie */ genrandom(buf_getwriteptr(ses.writepayload, 16), 16); buf_incrwritepos(ses.writepayload, 16); /* kex algos */ buf_put_algolist(ses.writepayload, sshkex); /* server_host_key_algorithms */ buf_put_algolist(ses.writepayload, sshhostkey); /* encryption_algorithms_client_to_server */ buf_put_algolist(ses.writepayload, sshciphers); /* encryption_algorithms_server_to_client */ buf_put_algolist(ses.writepayload, sshciphers); /* mac_algorithms_client_to_server */ buf_put_algolist(ses.writepayload, sshhashes); /* mac_algorithms_server_to_client */ buf_put_algolist(ses.writepayload, sshhashes); /* compression_algorithms_client_to_server */ buf_put_algolist(ses.writepayload, sshcompress); /* compression_algorithms_server_to_client */ buf_put_algolist(ses.writepayload, sshcompress); /* languages_client_to_server */ buf_putstring(ses.writepayload, "", 0); /* languages_server_to_client */ buf_putstring(ses.writepayload, "", 0); /* first_kex_packet_follows - unimplemented for now */ buf_putbyte(ses.writepayload, 0x00); /* reserved unit32 */ buf_putint(ses.writepayload, 0); /* set up transmitted kex packet buffer for hashing. * This is freed after the end of the kex */ ses.transkexinit = buf_newcopy(ses.writepayload); encrypt_packet(); ses.dataallowed = 0; /* don't send other packets during kex */ ses.kexstate.sentkexinit = 1; }
static void send_msg_global_request_remotetcp(const char *addr, int port) { TRACE(("enter send_msg_global_request_remotetcp")) CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST); buf_putstring(ses.writepayload, "tcpip-forward", 13); buf_putbyte(ses.writepayload, 1); /* want_reply */ buf_putstring(ses.writepayload, addr, strlen(addr)); buf_putint(ses.writepayload, port); encrypt_packet(); TRACE(("leave send_msg_global_request_remotetcp")) }
/* Send a channel open failure message, with a corresponding reason * code (usually resource shortage or unknown chan type) */ static void send_msg_channel_open_failure(unsigned int remotechan, int reason, const unsigned char *text, const unsigned char *lang) { TRACE(("enter send_msg_channel_open_failure")); CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_FAILURE); buf_putint(ses.writepayload, remotechan); buf_putint(ses.writepayload, reason); buf_putstring(ses.writepayload, text, strlen((char*)text)); buf_putstring(ses.writepayload, lang, strlen((char*)lang)); encrypt_packet(); TRACE(("leave send_msg_channel_open_failure")); }
/* Create a new channel, and start the open request. This is intended * for X11, agent, tcp forwarding, and should be filled with channel-specific * options, with the calling function calling encrypt_packet() after * completion. It is mandatory for the caller to encrypt_packet() if * DROPBEAR_SUCCESS is returned */ int send_msg_channel_open_init(int fd, const char * typestring) { struct Channel* chan; chan = newchannel(0, CHANNEL_ID_AGENT, 0, 0); if (!chan) { return DROPBEAR_FAILURE; } /* set fd non-blocking */ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { return DROPBEAR_FAILURE; } chan->infd = chan->outfd = fd; ses.maxfd = MAX(ses.maxfd, fd); /* now open the channel connection */ CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN); buf_putstring(ses.writepayload, typestring, strlen(typestring)); buf_putint(ses.writepayload, chan->index); buf_putint(ses.writepayload, RECV_MAXWINDOW); buf_putint(ses.writepayload, RECV_MAXPACKET); return DROPBEAR_SUCCESS; }
static void send_msg_service_request(char* servicename) { TRACE(("enter send_msg_service_request: servicename='%s'", servicename)) CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_SERVICE_REQUEST); buf_putstring(ses.writepayload, servicename, strlen(servicename)); encrypt_packet(); TRACE(("leave send_msg_service_request")) }
/* Executed upon receiving a kexinit message from the client to initiate * key exchange. If we haven't already done so, we send the list of our * preferred algorithms. The client's requested algorithms are processed, * and we calculate the first portion of the key-exchange-hash for used * later in the key exchange. No response is sent, as the client should * initiate the diffie-hellman key exchange */ void recv_msg_kexinit() { TRACE(("enter recv_msg_kexinit")); if (!ses.kexstate.sentkexinit) { /* we need to send a kex packet */ send_msg_kexinit(); TRACE(("continue recv_msg_kexinit: sent kexinit")); } /* read the client's choice of algos */ read_kex(); /* start the kex hash */ ses.kexhashbuf = buf_new(MAX_KEXHASHBUF); /* V_C, the client's version string (CR and NL excluded) */ buf_putstring(ses.kexhashbuf, ses.remoteident, strlen((char*)ses.remoteident)); /* V_S, the server's version string (CR and NL excluded) */ buf_putstring(ses.kexhashbuf, (unsigned char*)LOCAL_IDENT, strlen(LOCAL_IDENT)); /* I_C, the payload of the client's SSH_MSG_KEXINIT */ buf_setpos(ses.payload, 0); buf_putstring(ses.kexhashbuf, buf_getptr(ses.payload, ses.payload->len), ses.payload->len); /* I_S, the payload of the server's SSH_MSG_KEXINIT */ buf_putstring(ses.kexhashbuf, buf_getptr(ses.transkexinit, ses.transkexinit->len), ses.transkexinit->len); buf_free(ses.transkexinit); ses.transkexinit = NULL; /* the rest of ses.kexhashbuf will be done after DH exchange */ ses.kexstate.recvkexinit = 1; ses.expecting = SSH_MSG_KEXDH_INIT; TRACE(("leave recv_msg_kexinit")); }
/* send the signal causing the exit to the client */ void send_msg_chansess_exitsignal(struct Channel * channel, struct ChanSess * chansess) { int i; char* signame = NULL; assert(chansess->exited); assert(chansess->exitsignal > 0); CHECKCLEARTOWRITE(); /* we check that we can match a signal name, otherwise * don't send anything */ i = 0; while (signames[i].name != 0) { if (signames[i].signal == chansess->exitsignal) { signame = signames[i].name; break; } i++; } if (signame == NULL) { return; } buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_REQUEST); buf_putint(ses.writepayload, channel->remotechan); buf_putstring(ses.writepayload, "exit-signal", 11); buf_putbyte(ses.writepayload, 0); /* boolean FALSE */ buf_putstring(ses.writepayload, signame, strlen(signame)); buf_putbyte(ses.writepayload, chansess->exitcore); buf_putstring(ses.writepayload, "", 0); /* error msg */ buf_putstring(ses.writepayload, "", 0); /* lang */ encrypt_packet(); }
static void tcp_acceptor(struct Listener *listener, int sock) { int fd; struct sockaddr_storage addr; int len; char ipstring[NI_MAXHOST], portstring[NI_MAXSERV]; struct TCPListener *tcpinfo = (struct TCPListener*)(listener->typedata); len = sizeof(addr); fd = accept(sock, (struct sockaddr*)&addr, &len); if (fd < 0) { return; } if (getnameinfo((struct sockaddr*)&addr, len, ipstring, sizeof(ipstring), portstring, sizeof(portstring), NI_NUMERICHOST | NI_NUMERICSERV) != 0) { return; } if (send_msg_channel_open_init(fd, tcpinfo->chantype) == DROPBEAR_SUCCESS) { buf_putstring(ses.writepayload, tcpinfo->sendaddr, strlen(tcpinfo->sendaddr)); buf_putint(ses.writepayload, tcpinfo->sendport); buf_putstring(ses.writepayload, ipstring, strlen(ipstring)); buf_putint(ses.writepayload, atol(portstring)); encrypt_packet(); } else { /* XXX debug? */ close(fd); } }
/* Output a comma seperated list of algorithms to a buffer */ void buf_put_algolist(buffer * buf, algo_type localalgos[]) { unsigned int pos = 0, i, len; char str[50]; /* enough for local algo storage */ for (i = 0; localalgos[i].name != NULL; i++) { if (localalgos[i].usable) { len = strlen(localalgos[i].name); memcpy(&str[pos], localalgos[i].name, len); pos += len; str[pos] = ','; pos++; } } buf_putstring(buf, str, pos-1); }
static int send_msg_channel_open_x11(int fd, struct sockaddr_in* addr) { char* ipstring = NULL; if (send_msg_channel_open_init(fd, &chan_x11) == DROPBEAR_SUCCESS) { ipstring = inet_ntoa(addr->sin_addr); buf_putstring(ses.writepayload, ipstring, strlen(ipstring)); buf_putint(ses.writepayload, addr->sin_port); encrypt_packet(); return DROPBEAR_SUCCESS; } else { return DROPBEAR_FAILURE; } }
void send_msg_kexdh_init() { TRACE(("send_msg_kexdh_init()")) CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT); switch (ses.newkeys->algo_kex->mode) { case DROPBEAR_KEX_NORMAL_DH: if (ses.newkeys->algo_kex != cli_ses.param_kex_algo || !cli_ses.dh_param) { if (cli_ses.dh_param) { free_kexdh_param(cli_ses.dh_param); } cli_ses.dh_param = gen_kexdh_param(); } buf_putmpint(ses.writepayload, &cli_ses.dh_param->pub); break; case DROPBEAR_KEX_ECDH: #ifdef DROPBEAR_ECDH if (ses.newkeys->algo_kex != cli_ses.param_kex_algo || !cli_ses.ecdh_param) { if (cli_ses.ecdh_param) { free_kexecdh_param(cli_ses.ecdh_param); } cli_ses.ecdh_param = gen_kexecdh_param(); } buf_put_ecc_raw_pubkey_string(ses.writepayload, &cli_ses.ecdh_param->key); #endif break; #ifdef DROPBEAR_CURVE25519 case DROPBEAR_KEX_CURVE25519: if (ses.newkeys->algo_kex != cli_ses.param_kex_algo || !cli_ses.curve25519_param) { if (cli_ses.curve25519_param) { free_kexcurve25519_param(cli_ses.curve25519_param); } cli_ses.curve25519_param = gen_kexcurve25519_param(); } buf_putstring(ses.writepayload, cli_ses.curve25519_param->pub, CURVE25519_LEN); #endif break; } cli_ses.param_kex_algo = ses.newkeys->algo_kex; encrypt_packet(); ses.requirenext[0] = SSH_MSG_KEXDH_REPLY; ses.requirenext[1] = SSH_MSG_KEXINIT; }
/* send the exitstatus to the client */ void send_msg_chansess_exitstatus(struct Channel * channel, struct ChanSess * chansess) { assert(chansess->exited); assert(chansess->exitsignal == -1); CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_REQUEST); buf_putint(ses.writepayload, channel->remotechan); buf_putstring(ses.writepayload, "exit-status", 11); buf_putbyte(ses.writepayload, 0); /* boolean FALSE */ buf_putint(ses.writepayload, chansess->exitstatus); encrypt_packet(); }
/* Output a comma separated list of algorithms to a buffer */ void buf_put_algolist(buffer * buf, algo_type localalgos[]) { unsigned int i, len; unsigned int donefirst = 0; buffer *algolist = NULL; algolist = buf_new(300); for (i = 0; localalgos[i].name != NULL; i++) { if (localalgos[i].usable) { if (donefirst) buf_putbyte(algolist, ','); donefirst = 1; len = strlen(localalgos[i].name); buf_putbytes(algolist, (const unsigned char *) localalgos[i].name, len); } } buf_putstring(buf, (const char*)algolist->data, algolist->len); buf_free(algolist); }
/* Output a comma separated list of algorithms to a buffer */ void buf_put_algolist(buffer * buf, algo_type localalgos[]) { unsigned int pos = 0, i, len; char str[50]; /* enough for local algo storage */ for (i = 0; localalgos[i].name != NULL; i++) { if (localalgos[i].usable) { /* Avoid generating a trailing comma */ if (pos) str[pos++] = ','; len = strlen(localalgos[i].name); memcpy(&str[pos], localalgos[i].name, len); pos += len; } } str[pos]=0; /* Debug this */ TRACE(("buf_put_algolist: %s", str)) buf_putstring(buf, str, pos); }
/* Reads data from the server's program/shell/etc, and puts it in a * channel_data packet to send. * chan is the remote channel, isextended is 0 if it is normal data, 1 * if it is extended data. if it is extended, then the type is in * exttype */ static void send_msg_channel_data(struct Channel *channel, int isextended, unsigned int exttype) { buffer *buf; int len; unsigned int maxlen; int fd; TRACE(("enter send_msg_channel_data")); TRACE(("extended = %d type = %d", isextended, exttype)); CHECKCLEARTOWRITE(); assert(!channel->sentclosed); if (isextended) { if (channel->erreof) { TRACE(("leave send_msg_channel_data: erreof already set")); return; } assert(exttype == SSH_EXTENDED_DATA_STDERR); fd = channel->errfd; } else { if (channel->transeof) { TRACE(("leave send_msg_channel_data: transeof already set")); return; } fd = channel->outfd; } assert(fd >= 0); maxlen = MIN(channel->transwindow, channel->transmaxpacket); /* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and * exttype if is extended */ maxlen = MIN(maxlen, ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0)); if (maxlen == 0) { TRACE(("leave send_msg_channel_data: no window")); return; /* the data will get written later */ } /* read the data */ buf = buf_new(maxlen); len = read(fd, buf_getwriteptr(buf, maxlen), maxlen); if (len <= 0) { /* on error etc, send eof */ if (errno != EINTR) { if (isextended) { channel->erreof = 1; } else { channel->transeof = 1; } if ((channel->erreof || channel->errfd == -1) && channel->transeof) { send_msg_channel_eof(channel); } } buf_free(buf); TRACE(("leave send_msg_channel_data: len <= 0, erreof %d transeof %d", channel->erreof, channel->transeof)); return; } buf_incrlen(buf, len); buf_putbyte(ses.writepayload, isextended ? SSH_MSG_CHANNEL_EXTENDED_DATA : SSH_MSG_CHANNEL_DATA); buf_putint(ses.writepayload, channel->remotechan); if (isextended) { buf_putint(ses.writepayload, exttype); } buf_putstring(ses.writepayload, buf_getptr(buf, len), len); buf_free(buf); channel->transwindow -= len; encrypt_packet(); TRACE(("leave send_msg_channel_data")); }
/* puts an entire buffer as a SSH string. ignore pos of buf_str. */ void buf_putbufstring(buffer *buf, const buffer* buf_str) { buf_putstring(buf, (const char*)buf_str->data, buf_str->len); }
void recv_msg_userauth_info_request() { unsigned char *name = NULL; unsigned char *instruction = NULL; unsigned int num_prompts = 0; unsigned int i; unsigned char *prompt = NULL; unsigned int echo = 0; unsigned char *response = NULL; TRACE(("enter recv_msg_recv_userauth_info_request")) /* Let the user know what password/host they are authing for */ if (!cli_ses.interact_request_received) { fprintf(stderr, "Login for %s@%s\n", cli_opts.username, //cli_opts.remotehost); cli_opts.remote_name_str); } cli_ses.interact_request_received = 1; name = buf_getstring(ses.payload, NULL); instruction = buf_getstring(ses.payload, NULL); /* language tag */ buf_eatstring(ses.payload); num_prompts = buf_getint(ses.payload); if (num_prompts >= DROPBEAR_MAX_CLI_INTERACT_PROMPTS) { dropbear_exit("Too many prompts received for keyboard-interactive"); } /* we'll build the response as we go */ CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_INFO_RESPONSE); buf_putint(ses.writepayload, num_prompts); if (strlen(name) > 0) { cleantext(name); fprintf(stderr, "%s", name); } m_free(name); if (strlen(instruction) > 0) { cleantext(instruction); fprintf(stderr, "%s", instruction); } m_free(instruction); for (i = 0; i < num_prompts; i++) { unsigned int response_len = 0; prompt = buf_getstring(ses.payload, NULL); cleantext(prompt); echo = buf_getbool(ses.payload); if (!echo) { unsigned char* p = getpass_or_cancel(prompt); response = m_strdup(p); m_burn(p, strlen(p)); } else { response = get_response(prompt); } response_len = strlen(response); buf_putstring(ses.writepayload, response, response_len); m_burn(response, response_len); m_free(response); } encrypt_packet(); TRACE(("leave recv_msg_recv_userauth_info_request")) }
int packet_auth(struct buf *b, struct buf *b2) { crypto_uint8 ch, flagsignature; long long pos, i, count, sign_bytes = 0; crypto_uint32 len; const char *pkname; int (*sign_open)(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *) = 0; int (*parsesignpk)(unsigned char *, const unsigned char *, long long) = 0; int (*parsesignature)(unsigned char *, const unsigned char *, long long) = 0; void (*putsignpk)(struct buf *, const unsigned char *) = 0; void (*putsignpkbase64)(struct buf *, const unsigned char *) = 0; unsigned char pk[sshcrypto_sign_PUBLICKEYMAX]; unsigned char sig[sshcrypto_sign_MAX]; unsigned long long smlen; buf_purge(b); /* parse "ssh-userauth" */ pos = 0; if (!packet_getall(b, SSH_MSG_SERVICE_REQUEST)) bug(); pos = packetparser_uint8(b->buf, b->len, pos, &ch); /* SSH_MSG_SERVICE_REQUEST */ if (ch != SSH_MSG_SERVICE_REQUEST) bug_proto(); pos = packetparser_uint32(b->buf, b->len, pos, &len); /* "ssh-userauth" */ if (len != 12) bug_proto(); pos = packetparser_skip(b->buf, b->len, pos, len); if (!byte_isequal(b->buf + pos - len, len, "ssh-userauth")) bug_proto(); pos = packetparser_end(b->buf, b->len, pos); /* send service accept */ b->buf[0] = SSH_MSG_SERVICE_ACCEPT; packet_put(b); if (!packet_sendall()) bug(); for (count = 0; count < 32; ++count) { /* receive userauth request */ pkname = "unknown"; pos = 0; buf_purge(b); if (!packet_getall(b, SSH_MSG_USERAUTH_REQUEST)) bug(); pos = packetparser_uint8(b->buf, b->len, pos, &ch); /* SSH_MSG_USERAUTH_REQUEST */ if (ch != SSH_MSG_USERAUTH_REQUEST) bug_proto(); pos = packetparser_uint32(b->buf, b->len, pos, &len); /* name */ if (len >= PACKET_NAMESIZE) bug_proto(); pos = packetparser_copy(b->buf, b->len, pos, (unsigned char *)packet.name, len); packet.name[len] = 0; pos = packetparser_uint32(b->buf, b->len, pos, &len); /* "ssh-connection" */ if (len != 14) bug_proto(); pos = packetparser_skip(b->buf, b->len, pos, len); if (!byte_isequal(b->buf + pos - len, len, "ssh-connection")) bug_proto(); pos = packetparser_uint32(b->buf, b->len, pos, &len); /* publickey/password/hostbased/none */ pos = packetparser_skip(b->buf, b->len, pos, len); if (str_equaln((char *)b->buf + pos - len, len, "none")) pkname = "none"; if (str_equaln((char *)b->buf + pos - len, len, "password")) pkname = "password"; if (str_equaln((char *)b->buf + pos - len, len, "hostbased")) pkname = "hostbased"; if (str_equaln((char *)b->buf + pos - len, len, "publickey")) { pos = packetparser_uint8(b->buf, b->len, pos, &flagsignature); pos = packetparser_uint32(b->buf, b->len, pos, &len); /* public key algorithm name */ pos = packetparser_skip(b->buf, b->len, pos, len); if (b->buf[pos] != 0) bug_proto(); pkname = (char *)b->buf + pos - len; /* XXX */ sign_open = 0; parsesignpk = 0; putsignpk = 0; putsignpkbase64 = 0; parsesignature = 0; sign_bytes = 0; for (i = 0; sshcrypto_keys[i].name; ++i) { if (!sshcrypto_keys[i].sign_flagclient) continue; if (!str_equaln(pkname, len, sshcrypto_keys[i].name)) continue; pkname = sshcrypto_keys[i].name; sign_open = sshcrypto_keys[i].sign_open; parsesignature = sshcrypto_keys[i].parsesignature; parsesignpk = sshcrypto_keys[i].parsesignpk; putsignpk = sshcrypto_keys[i].buf_putsignpk; putsignpkbase64 = sshcrypto_keys[i].buf_putsignpkbase64; sign_bytes = sshcrypto_keys[i].sign_bytes; break; } if (sign_open && parsesignpk && putsignpk && putsignpkbase64 && parsesignature) { pos = packetparser_uint32(b->buf, b->len, pos, &len); /* public key blob */ pos = packetparser_skip(b->buf, b->len, pos, len); if (!parsesignpk(pk, b->buf + pos - len, len)) bug_proto(); if (!flagsignature) { /* 'publickey' ... without signature */ buf_purge(b); buf_putnum8(b, SSH_MSG_USERAUTH_PK_OK); buf_putstring(b, pkname); putsignpk(b, pk); packet_put(b); if (!packet_sendall()) bug(); continue; } /* 'publickey' ... with signature */ pos = packetparser_uint32(b->buf, b->len, pos, &len); /* signature blob */ pos = packetparser_skip(b->buf, b->len, pos, len); if (!parsesignature(sig, b->buf + pos - len, len)) bug_proto(); pos = packetparser_end(b->buf, b->len, pos); purge(b->buf + b->len - len - 4, len + 4); b->len -= len + 4; /* authenticate user - verify signature */ buf_purge(b2); buf_put(b2, sig, sign_bytes); buf_putstringlen(b2, packet.sessionid, sshcrypto_hash_bytes); buf_put(b2, b->buf, b->len); buf_purge(b); if (b->alloc <= b2->len) bug_nomem(); if (sign_open(b->buf, &smlen, b2->buf, b2->len, pk) != 0) { errno = EAUTH; bug(); } b->len = smlen; buf_purge(b); /* authorize user - using authorized_keys */ buf_purge(b); putsignpkbase64(b, pk); buf_putnum8(b, 0); if (subprocess_auth(packet.name, pkname, (char *)b->buf) == 0) goto authorized; } } /* reject */ log_i5("auth: ", packet.name, ": ", pkname, " rejected"); buf_purge(b); buf_putnum8(b, SSH_MSG_USERAUTH_FAILURE); buf_putstring(b,"publickey"); buf_putnum8(b, 0); packet_put(b); if (!packet_sendall()) bug(); } log_w1("auth: too many authentication tries"); return 0; authorized: /* authenticated + authorized */ log_i5("auth: ", packet.name, ": ", pkname, " accepted"); buf_purge(b); buf_putnum8(b, SSH_MSG_USERAUTH_SUCCESS); buf_putstring(b,"ssh-connection"); packet_put(b); if (!packet_sendall()) bug(); purge(pk, sizeof pk); purge(sig, sizeof sig); return 1; }