static int kbdauth_info_get(SSH_SESSION *session){ STRING *name; /* name of the "asking" window showed to client */ STRING *instruction; STRING *tmp; u32 nprompts; u32 i; enter_function(); name=buffer_get_ssh_string(session->in_buffer); instruction=buffer_get_ssh_string(session->in_buffer); tmp=buffer_get_ssh_string(session->in_buffer); buffer_get_u32(session->in_buffer,&nprompts); if(!name || !instruction || !tmp){ if(name) free(name); if(instruction) free(instruction); // tmp must be empty if we got here ssh_set_error(session,SSH_FATAL,"Invalid USERAUTH_INFO_REQUEST msg"); leave_function(); return SSH_AUTH_ERROR; } if(tmp) free(tmp); // no use if(!session->kbdint) session->kbdint=kbdint_new(); else kbdint_clean(session->kbdint); session->kbdint->name=string_to_char(name); free(name); session->kbdint->instruction=string_to_char(instruction); free(instruction); nprompts=ntohl(nprompts); if(nprompts>KBDINT_MAX_PROMPT){ ssh_set_error(session,SSH_FATAL,"Too much prompt asked from server: %lu(0x%.8lx)",nprompts,nprompts); leave_function(); return SSH_AUTH_ERROR; } session->kbdint->nprompts=nprompts; session->kbdint->prompts=malloc(nprompts*sizeof(char *)); memset(session->kbdint->prompts,0,nprompts*sizeof(char *)); session->kbdint->echo=malloc(nprompts); memset(session->kbdint->echo,0,nprompts); for(i=0;i<nprompts;++i){ tmp=buffer_get_ssh_string(session->in_buffer); buffer_get_u8(session->in_buffer,&session->kbdint->echo[i]); if(!tmp){ ssh_set_error(session,SSH_FATAL,"Short INFO_REQUEST packet"); leave_function(); return SSH_AUTH_ERROR; } session->kbdint->prompts[i]=string_to_char(tmp); free(tmp); } leave_function(); return SSH_AUTH_INFO; /* we are not auth. but we parsed the packet */ }
PUBLIC_KEY *publickey_from_string(SSH_SESSION *session, STRING *pubkey_s){ BUFFER *tmpbuf=buffer_new(); STRING *type_s; char *type; buffer_add_data(tmpbuf,pubkey_s->string,string_len(pubkey_s)); type_s=buffer_get_ssh_string(tmpbuf); if(!type_s){ buffer_free(tmpbuf); ssh_set_error(session,SSH_FATAL,"Invalid public key format"); return NULL; } type=string_to_char(type_s); free(type_s); if(!strcmp(type,"ssh-dss")){ free(type); return publickey_make_dss(session, tmpbuf); } if(!strcmp(type,"ssh-rsa")){ free(type); return publickey_make_rsa(session, tmpbuf,"ssh-rsa"); } if(!strcmp(type,"ssh-rsa1")){ free(type); return publickey_make_rsa(session, tmpbuf,"ssh-rsa1"); } ssh_set_error(session,SSH_FATAL,"unknown public key protocol %s",type); buffer_free(tmpbuf); free(type); return NULL; }
int ssh_get_kex(SSH_SESSION *session,int server_kex ){ STRING *str; char *strings[10]; int i; if(packet_wait(session,SSH2_MSG_KEXINIT,1)) return -1; if(buffer_get_data(session->in_buffer,session->server_kex.cookie,16)!=16){ ssh_set_error(session,SSH_FATAL,"get_kex(): no cookie in packet"); return -1; } hashbufin_add_cookie(session,session->server_kex.cookie); memset(strings,0,sizeof(char *)*10); for(i=0;i<10;++i){ str=buffer_get_ssh_string(session->in_buffer); if(!str) break; if(str){ buffer_add_ssh_string(session->in_hashbuf,str); strings[i]=string_to_char(str); free(str); } else strings[i]=NULL; } /* copy the server kex info into an array of strings */ if(server_kex){ session->client_kex.methods=malloc( 10 * sizeof(char **)); for(i=0;i<10;++i) session->client_kex.methods[i]=strings[i]; } else { // client session->server_kex.methods=malloc( 10 * sizeof(char **)); for(i=0;i<10;++i) session->server_kex.methods[i]=strings[i]; } return 0; }
/* * Print a button */ static void print_button(WINDOW *win, char *label, int y, int x, int selected) { int i; int state = 0; const int *indx = dlg_index_wchars(label); int limit = dlg_count_wchars(label); chtype key_attr = (selected ? button_key_active_attr : button_key_inactive_attr); chtype label_attr = (selected ? button_label_active_attr : button_label_inactive_attr); (void) wmove(win, y, x); wattrset(win, selected ? button_active_attr : button_inactive_attr); (void) waddstr(win, "<"); wattrset(win, label_attr); for (i = 0; i < limit; ++i) { int first = indx[i]; int last = indx[i + 1]; switch (state) { case 0: #ifdef USE_WIDE_CURSES if ((last - first) != 1) { const char *temp = (label + first); int cmp = string_to_char(&temp); if (dlg_isupper(cmp)) { wattrset(win, key_attr); state = 1; } break; } #endif if (dlg_isupper(UCH(label[first]))) { wattrset(win, key_attr); state = 1; } break; case 1: wattrset(win, label_attr); state = 2; break; } waddnstr(win, label + first, last - first); } wattrset(win, selected ? button_active_attr : button_inactive_attr); (void) waddstr(win, ">"); (void) wmove(win, y, x + ((int) strspn(label, " ")) + 1); }
/* * Find the first uppercase character in the label, which we may use for an * abbreviation. */ int dlg_button_to_char(const char *label) { int cmp = -1; while (*label != 0) { cmp = string_to_char(&label); if (dlg_isupper(cmp)) { break; } } return cmp; }
/* caller has to free commment */ struct ssh_public_key_struct *agent_get_next_ident(struct ssh_session_struct *session, char **comment) { struct ssh_public_key_struct *pubkey = NULL; struct ssh_string_struct *blob = NULL; struct ssh_string_struct *tmp = NULL; if (session->agent->count == 0) { return NULL; } switch(session->version) { case 1: return NULL; case 2: /* get the blob */ blob = buffer_get_ssh_string(session->agent->ident); if (blob == NULL) { return NULL; } /* get the comment */ tmp = buffer_get_ssh_string(session->agent->ident); if (tmp == NULL) { string_free(blob); return NULL; } if (comment) { *comment = string_to_char(tmp); } else { string_free(blob); string_free(tmp); return NULL; } string_free(tmp); /* get key from blob */ pubkey = publickey_from_string(session, blob); string_free(blob); break; default: return NULL; } return pubkey; }
ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s) { ssh_buffer tmpbuf = NULL; ssh_string type_s = NULL; char *type_c = NULL; int type; tmpbuf = buffer_new(); if (tmpbuf == NULL) { return NULL; } if (buffer_add_data(tmpbuf, string_data(pubkey_s), string_len(pubkey_s)) < 0) { goto error; } type_s = buffer_get_ssh_string(tmpbuf); if (type_s == NULL) { ssh_set_error(session,SSH_FATAL,"Invalid public key format"); goto error; } type_c = string_to_char(type_s); string_free(type_s); if (type_c == NULL) { goto error; } type = ssh_type_from_name(type_c); SAFE_FREE(type_c); switch (type) { case TYPE_DSS: return publickey_make_dss(session, tmpbuf); case TYPE_RSA: case TYPE_RSA1: return publickey_make_rsa(session, tmpbuf, type); } ssh_set_error(session, SSH_FATAL, "Unknown public key protocol %s", ssh_type_to_char(type)); error: buffer_free(tmpbuf); return NULL; }
/* * Match a given character against the beginning of the string, ignoring case * of the given character. The matching string must begin with an uppercase * character. */ int dlg_match_char(int ch, const char *string) { if (string != 0) { int cmp2 = string_to_char(&string); #ifdef USE_WIDE_CURSES wint_t cmp1 = dlg_toupper(ch); if (cmp2 != 0 && (wchar_t) cmp1 == (wchar_t) dlg_toupper(cmp2)) { return TRUE; } #else if (ch > 0 && ch < 256) { if (dlg_toupper(ch) == dlg_toupper(cmp2)) return TRUE; } #endif } return FALSE; }
/* TODO : split this function in two so it becomes smaller */ SIGNATURE *signature_from_string(SSH_SESSION *session, STRING *signature,PUBLIC_KEY *pubkey,int needed_type){ #ifdef HAVE_LIBGCRYPT gcry_sexp_t sig; #elif defined HAVE_LIBCRYPTO DSA_SIG *sig; STRING *r,*s; #endif SIGNATURE *sign=malloc(sizeof(SIGNATURE)); BUFFER *tmpbuf=buffer_new(); STRING *rs; STRING *type_s,*e; int len,rsalen; char *type; buffer_add_data(tmpbuf,signature->string,string_len(signature)); type_s=buffer_get_ssh_string(tmpbuf); if(!type_s){ ssh_set_error(session,SSH_FATAL,"Invalid signature packet"); buffer_free(tmpbuf); return NULL; } type=string_to_char(type_s); free(type_s); switch(needed_type){ case TYPE_DSS: if(strcmp(type,"ssh-dss")){ ssh_set_error(session,SSH_FATAL,"Invalid signature type : %s",type); buffer_free(tmpbuf); free(type); return NULL; } break; case TYPE_RSA: if(strcmp(type,"ssh-rsa")){ ssh_set_error(session,SSH_FATAL,"Invalid signature type : %s",type); buffer_free(tmpbuf); free(type); return NULL; } break; default: ssh_set_error(session,SSH_FATAL,"Invalid signature type : %s",type); free(type); buffer_free(tmpbuf); return NULL; } free(type); switch(needed_type){ case TYPE_DSS: rs=buffer_get_ssh_string(tmpbuf); buffer_free(tmpbuf); if(!rs || string_len(rs)!=40){ /* 40 is the dual signature blob len. */ if(rs) free(rs); return NULL; } /* we make use of strings (because we have all-made functions to convert them to bignums (ou pas ;)*/ #ifdef HAVE_LIBGCRYPT gcry_sexp_build(&sig,NULL,"(sig-val(dsa(r %b)(s %b)))",20,rs->string,20,rs->string+20); #elif defined HAVE_LIBCRYPTO r=string_new(20); s=string_new(20); string_fill(r,rs->string,20); string_fill(s,rs->string+20,20); sig=DSA_SIG_new(); sig->r=make_string_bn(r); /* is that really portable ? Openssh's hack isn't better */ sig->s=make_string_bn(s); free(r); free(s); #endif #ifdef DEBUG_CRYPTO ssh_print_hexa("r",rs->string,20); ssh_print_hexa("s",rs->string+20,20); #endif free(rs); sign->type=TYPE_DSS; sign->dsa_sign=sig; return sign; case TYPE_RSA: e=buffer_get_ssh_string(tmpbuf); buffer_free(tmpbuf); if(!e){ return NULL; } len=string_len(e); #ifdef HAVE_LIBGCRYPT rsalen=(gcry_pk_get_nbits(pubkey->rsa_pub)+7)/8; #elif defined HAVE_LIBCRYPTO rsalen=RSA_size(pubkey->rsa_pub); #endif if(len>rsalen){ free(e); free(sign); ssh_set_error(session,SSH_FATAL,"signature too big ! %d instead of %d",len,rsalen); return NULL; } if(len<rsalen) ssh_log(session,SSH_LOG_RARE,"RSA signature len %d < %d",len,rsalen); sign->type=TYPE_RSA; #ifdef HAVE_LIBGCRYPT gcry_sexp_build(&sig,NULL,"(sig-val(rsa(s %b)))",string_len(e),e->string); sign->rsa_sign=sig; #elif defined HAVE_LIBCRYPTO sign->rsa_sign=e; #endif #ifdef DEBUG_CRYPTO ssh_say(0,"Len : %d\n",len); ssh_print_hexa("rsa signature",e->string,len); #endif #ifdef HAVE_LIBGCRYPT free(e); #endif return sign; default: return NULL; } }
static int wait_auth_status(ssh_session session, int kbdint) { char *auth_methods = NULL; ssh_string auth; int rc = SSH_AUTH_ERROR; int cont = 1; uint8_t partial = 0; enter_function(); while (cont) { if (packet_read(session) != SSH_OK) { break; } if (packet_translate(session) != SSH_OK) { break; } switch (session->in_packet.type) { case SSH2_MSG_USERAUTH_FAILURE: auth = buffer_get_ssh_string(session->in_buffer); if (auth == NULL || buffer_get_u8(session->in_buffer, &partial) != 1) { ssh_set_error(session, SSH_FATAL, "Invalid SSH_MSG_USERAUTH_FAILURE message"); leave_function(); return SSH_AUTH_ERROR; } auth_methods = string_to_char(auth); if (auth_methods == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); string_free(auth); leave_function(); return SSH_AUTH_ERROR; } if (partial) { rc = SSH_AUTH_PARTIAL; ssh_set_error(session, SSH_NO_ERROR, "Partial success. Authentication that can continue: %s", auth_methods); } else { rc = SSH_AUTH_DENIED; ssh_set_error(session, SSH_REQUEST_DENIED, "Access denied. Authentication that can continue: %s", auth_methods); session->auth_methods = 0; if (strstr(auth_methods, "password") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_PASSWORD; } if (strstr(auth_methods, "keyboard-interactive") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_INTERACTIVE; } if (strstr(auth_methods, "publickey") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_PUBLICKEY; } if (strstr(auth_methods, "hostbased") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_HOSTBASED; } } string_free(auth); SAFE_FREE(auth_methods); cont = 0; break; case SSH2_MSG_USERAUTH_PK_OK: /* SSH monkeys have defined the same number for both */ /* SSH_MSG_USERAUTH_PK_OK and SSH_MSG_USERAUTH_INFO_REQUEST */ /* which is not really smart; */ /*case SSH2_MSG_USERAUTH_INFO_REQUEST: */ if (kbdint) { rc = SSH_AUTH_INFO; cont = 0; break; } /* continue through success */ case SSH2_MSG_USERAUTH_SUCCESS: rc = SSH_AUTH_SUCCESS; cont = 0; break; case SSH2_MSG_USERAUTH_BANNER: { ssh_string banner; banner = buffer_get_ssh_string(session->in_buffer); if (banner == NULL) { ssh_log(session, SSH_LOG_PACKET, "The banner message was invalid. Continuing though\n"); break; } ssh_log(session, SSH_LOG_PACKET, "Received a message banner\n"); string_free(session->banner); /* erase the older one */ session->banner = banner; break; } default: packet_parse(session); break; } } leave_function(); return rc; }
int ssh_get_kex(SSH_SESSION *session, int server_kex) { STRING *str = NULL; char *strings[10]; int i; enter_function(); if (packet_wait(session, SSH2_MSG_KEXINIT, 1) != SSH_OK) { leave_function(); return -1; } if (buffer_get_data(session->in_buffer,session->server_kex.cookie,16) != 16) { ssh_set_error(session, SSH_FATAL, "get_kex(): no cookie in packet"); leave_function(); return -1; } if (hashbufin_add_cookie(session, session->server_kex.cookie) < 0) { ssh_set_error(session, SSH_FATAL, "get_kex(): adding cookie failed"); leave_function(); return -1; } memset(strings, 0, sizeof(char *) * 10); for (i = 0; i < 10; i++) { str = buffer_get_ssh_string(session->in_buffer); if (str == NULL) { break; } if (buffer_add_ssh_string(session->in_hashbuf, str) < 0) { goto error; } strings[i] = string_to_char(str); if (strings[i] == NULL) { goto error; } string_free(str); str = NULL; } /* copy the server kex info into an array of strings */ if (server_kex) { session->client_kex.methods = malloc(10 * sizeof(char **)); if (session->client_kex.methods == NULL) { leave_function(); return -1; } for (i = 0; i < 10; i++) { session->client_kex.methods[i] = strings[i]; } } else { /* client */ session->server_kex.methods = malloc(10 * sizeof(char **)); if (session->server_kex.methods == NULL) { leave_function(); return -1; } for (i = 0; i < 10; i++) { session->server_kex.methods[i] = strings[i]; } } leave_function(); return 0; error: string_free(str); for (i = 0; i < 10; i++) { SAFE_FREE(strings[i]); } leave_function(); return -1; }
static void channel_rcv_request(SSH_SESSION *session) { CHANNEL *channel; STRING *request_s; char *request; u32 status; enter_function(); channel = channel_from_msg(session); if (channel == NULL) { ssh_log(session, SSH_LOG_FUNCTIONS, ssh_get_error(session)); leave_function(); return; } request_s = buffer_get_ssh_string(session->in_buffer); if (request_s == NULL) { ssh_log(session, SSH_LOG_PACKET, "Invalid MSG_CHANNEL_REQUEST"); leave_function(); return; } request = string_to_char(request_s); string_free(request_s); if (request == NULL) { leave_function(); return; } buffer_get_u8(session->in_buffer, (u8 *) &status); if (strcmp(request,"exit-status") == 0) { SAFE_FREE(request); ssh_log(session, SSH_LOG_PACKET, "received exit-status"); buffer_get_u32(session->in_buffer, &status); channel->exit_status = ntohl(status); leave_function(); return ; } if (strcmp(request, "exit-signal") == 0) { const char *core = "(core dumped)"; STRING *signal_s; char *signal; u8 i; SAFE_FREE(request); signal_s = buffer_get_ssh_string(session->in_buffer); if (signal_s == NULL) { ssh_log(session, SSH_LOG_PACKET, "Invalid MSG_CHANNEL_REQUEST"); leave_function(); return; } signal = string_to_char(signal_s); string_free(signal_s); if (signal == NULL) { leave_function(); return; } buffer_get_u8(session->in_buffer, &i); if (i == 0) { core = ""; } ssh_log(session, SSH_LOG_PACKET, "Remote connection closed by signal SIG %s %s", signal, core); SAFE_FREE(signal); leave_function(); return; } ssh_log(session, SSH_LOG_PACKET, "Unknown request %s", request); SAFE_FREE(request); leave_function(); }
static int channel_open(CHANNEL *channel, const char *type_c, int window, int maxpacket, BUFFER *payload) { SSH_SESSION *session = channel->session; STRING *type = NULL; u32 tmp = 0; enter_function(); channel->local_channel = ssh_channel_new_id(session); channel->local_maxpacket = maxpacket; channel->local_window = window; ssh_log(session, SSH_LOG_RARE, "Creating a channel %d with %d window and %d max packet", channel->local_channel, window, maxpacket); type = string_from_char(type_c); if (type == NULL) { leave_function(); return -1; } if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_OPEN) < 0 || buffer_add_ssh_string(session->out_buffer,type) < 0 || buffer_add_u32(session->out_buffer, htonl(channel->local_channel)) < 0 || buffer_add_u32(session->out_buffer, htonl(channel->local_window)) < 0 || buffer_add_u32(session->out_buffer, htonl(channel->local_maxpacket)) < 0) { string_free(type); leave_function(); return -1; } string_free(type); if (payload != NULL) { if (buffer_add_buffer(session->out_buffer, payload) < 0) { leave_function(); return -1; } } if (packet_send(session) != SSH_OK) { leave_function(); return -1; } ssh_log(session, SSH_LOG_RARE, "Sent a SSH_MSG_CHANNEL_OPEN type %s for channel %d", type_c, channel->local_channel); if (packet_wait(session, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, 1) != SSH_OK) { leave_function(); return -1; } switch(session->in_packet.type) { case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: buffer_get_u32(session->in_buffer, &tmp); if (channel->local_channel != ntohl(tmp)) { ssh_set_error(session, SSH_FATAL, "Server answered with sender channel number %lu instead of given %u", (long unsigned int) ntohl(tmp), channel->local_channel); leave_function(); return -1; } buffer_get_u32(session->in_buffer, &tmp); channel->remote_channel = ntohl(tmp); buffer_get_u32(session->in_buffer, &tmp); channel->remote_window = ntohl(tmp); buffer_get_u32(session->in_buffer,&tmp); channel->remote_maxpacket=ntohl(tmp); ssh_log(session, SSH_LOG_PROTOCOL, "Received a CHANNEL_OPEN_CONFIRMATION for channel %d:%d", channel->local_channel, channel->remote_channel); ssh_log(session, SSH_LOG_PROTOCOL, "Remote window : %lu, maxpacket : %lu", (long unsigned int) channel->remote_window, (long unsigned int) channel->remote_maxpacket); channel->open = 1; leave_function(); return 0; case SSH2_MSG_CHANNEL_OPEN_FAILURE: { STRING *error_s; char *error; u32 code; buffer_get_u32(session->in_buffer, &tmp); buffer_get_u32(session->in_buffer, &code); error_s = buffer_get_ssh_string(session->in_buffer); error = string_to_char(error_s); string_free(error_s); if (error == NULL) { leave_function(); return -1; } ssh_set_error(session, SSH_REQUEST_DENIED, "Channel opening failure: channel %u error (%lu) %s", channel->local_channel, (long unsigned int) ntohl(code), error); SAFE_FREE(error); leave_function(); return -1; } default: ssh_set_error(session, SSH_FATAL, "Received unknown packet %d\n", session->in_packet.type); leave_function(); return -1; } leave_function(); return -1; }
static int wait_auth_status(SSH_SESSION *session,int kbdint){ int err=SSH_AUTH_ERROR; int cont=1; STRING *auth; u8 partial=0; int todo = 0; char *auth_methods = NULL; enter_function(); while(cont){ if(packet_read(session)) break; if(packet_translate(session)) break; switch(session->in_packet.type){ case SSH2_MSG_USERAUTH_FAILURE: auth = buffer_get_ssh_string(session->in_buffer); if(!auth || buffer_get_u8(session->in_buffer,&partial)!=1 ){ ssh_set_error(session,SSH_FATAL, "invalid SSH_MSG_USERAUTH_FAILURE message"); leave_function(); return SSH_AUTH_ERROR; } auth_methods = string_to_char(auth); if(partial) { err=SSH_AUTH_PARTIAL; ssh_set_error(session,SSH_NO_ERROR,"partial success, authentications that can continue : %s", auth_methods); } else { err=SSH_AUTH_DENIED; ssh_set_error(session,SSH_REQUEST_DENIED,"Access denied. authentications that can continue : %s", auth_methods); session->auth_methods = 0; if (strstr(auth_methods, "password") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_PASSWORD; } if (strstr(auth_methods, "keyboard-interactive") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_INTERACTIVE; } if (strstr(auth_methods, "publickey") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_PUBLICKEY; } if (strstr(auth_methods, "hostbased") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_HOSTBASED; } } free(auth); free(auth_methods); cont=0; break; case SSH2_MSG_USERAUTH_PK_OK: /* SSH monkeys have defined the same number for both */ /* SSH_MSG_USERAUTH_PK_OK and SSH_MSG_USERAUTH_INFO_REQUEST */ /* which is not really smart; */ /*case SSH2_MSG_USERAUTH_INFO_REQUEST: */ if(kbdint){ err=SSH_AUTH_INFO; cont=0; break; } /* continue through success */ case SSH2_MSG_USERAUTH_SUCCESS: err=SSH_AUTH_SUCCESS; cont=0; break; case SSH2_MSG_USERAUTH_BANNER: { STRING *banner=buffer_get_ssh_string(session->in_buffer); if(!banner){ ssh_say(1,"The banner message was invalid. continuing though\n"); break; } ssh_say(2,"Received a message banner\n"); if(session->banner) free(session->banner); /* erase the older one */ session->banner=banner; break; } default: packet_parse(session); break; } } leave_function(); return err; }
/** this is the banner showing a disclaimer to users who log in, * typicaly their right or the fact that they will be monitored * \brief get the issue banner from the server * \param session ssh session * \return NULL if there is no issue banner, else a string containing it. */ char *ssh_get_issue_banner(SSH_SESSION *session){ if(!session->banner) return NULL; return string_to_char(session->banner); }
/* TODO : split this function in two so it becomes smaller */ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature, ssh_public_key pubkey, int needed_type) { SIGNATURE *sign = NULL; ssh_buffer tmpbuf = NULL; ssh_string rs = NULL; ssh_string type_s = NULL; ssh_string e = NULL; char *type_c = NULL; int type; int len; int rsalen; #ifdef HAVE_LIBGCRYPT gcry_sexp_t sig; #elif defined HAVE_LIBCRYPTO DSA_SIG *sig = NULL; ssh_string r = NULL; ssh_string s = NULL; #endif sign = malloc(sizeof(SIGNATURE)); if (sign == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); return NULL; } tmpbuf = buffer_new(); if (tmpbuf == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); signature_free(sign); return NULL; } if (buffer_add_data(tmpbuf, string_data(signature), string_len(signature)) < 0) { signature_free(sign); buffer_free(tmpbuf); return NULL; } type_s = buffer_get_ssh_string(tmpbuf); if (type_s == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid signature packet"); signature_free(sign); buffer_free(tmpbuf); return NULL; } type_c = string_to_char(type_s); string_free(type_s); if (type_c == NULL) { signature_free(sign); buffer_free(tmpbuf); return NULL; } type = ssh_type_from_name(type_c); SAFE_FREE(type_c); if (needed_type != type) { ssh_set_error(session, SSH_FATAL, "Invalid signature type: %s", ssh_type_to_char(type)); signature_free(sign); buffer_free(tmpbuf); return NULL; } switch(needed_type) { case TYPE_DSS: rs = buffer_get_ssh_string(tmpbuf); buffer_free(tmpbuf); /* 40 is the dual signature blob len. */ if (rs == NULL || string_len(rs) != 40) { string_free(rs); signature_free(sign); return NULL; } /* we make use of strings (because we have all-made functions to convert * them to bignums (ou pas ;) */ #ifdef HAVE_LIBGCRYPT if (gcry_sexp_build(&sig, NULL, "(sig-val(dsa(r %b)(s %b)))", 20 ,string_data(rs), 20,(unsigned char *)string_data(rs) + 20)) { string_free(rs); signature_free(sign); return NULL; } #elif defined HAVE_LIBCRYPTO r = string_new(20); s = string_new(20); if (r == NULL || s == NULL) { string_free(r); string_free(s); string_free(rs); signature_free(sign); return NULL; } string_fill(r, string_data(rs), 20); string_fill(s, (char *)string_data(rs) + 20, 20); sig = DSA_SIG_new(); if (sig == NULL) { string_free(r); string_free(s); string_free(rs); signature_free(sign); return NULL; } sig->r = make_string_bn(r); /* is that really portable ? Openssh's hack isn't better */ sig->s = make_string_bn(s); string_free(r); string_free(s); if (sig->r == NULL || sig->s == NULL) { string_free(rs); DSA_SIG_free(sig); signature_free(sign); return NULL; } #endif #ifdef DEBUG_CRYPTO ssh_print_hexa("r", string_data(rs), 20); ssh_print_hexa("s", (const unsigned char *)string_data(rs) + 20, 20); #endif string_free(rs); sign->type = TYPE_DSS; sign->dsa_sign = sig; return sign; case TYPE_RSA: e = buffer_get_ssh_string(tmpbuf); buffer_free(tmpbuf); if (e == NULL) { signature_free(sign); return NULL; } len = string_len(e); #ifdef HAVE_LIBGCRYPT rsalen = (gcry_pk_get_nbits(pubkey->rsa_pub) + 7) / 8; #elif defined HAVE_LIBCRYPTO rsalen = RSA_size(pubkey->rsa_pub); #endif if (len > rsalen) { string_free(e); signature_free(sign); ssh_set_error(session, SSH_FATAL, "Signature too big! %d instead of %d", len, rsalen); return NULL; } if (len < rsalen) { ssh_log(session, SSH_LOG_RARE, "RSA signature len %d < %d", len, rsalen); } sign->type = TYPE_RSA; #ifdef HAVE_LIBGCRYPT if (gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))", string_len(e), string_data(e))) { signature_free(sign); string_free(e); return NULL; } sign->rsa_sign = sig; #elif defined HAVE_LIBCRYPTO sign->rsa_sign = e; #endif #ifdef DEBUG_CRYPTO ssh_log(session, SSH_LOG_FUNCTIONS, "len e: %d", len); ssh_print_hexa("RSA signature", string_data(e), len); #endif #ifdef HAVE_LIBGCRYPT string_free(e); #endif return sign; default: return NULL; } return NULL; }
static int kbdauth_info_get(ssh_session session) { ssh_string name; /* name of the "asking" window showed to client */ ssh_string instruction; ssh_string tmp; uint32_t nprompts; uint32_t i; enter_function(); name = buffer_get_ssh_string(session->in_buffer); instruction = buffer_get_ssh_string(session->in_buffer); tmp = buffer_get_ssh_string(session->in_buffer); buffer_get_u32(session->in_buffer, &nprompts); if (name == NULL || instruction == NULL || tmp == NULL) { string_free(name); string_free(instruction); /* tmp if empty if we got here */ ssh_set_error(session, SSH_FATAL, "Invalid USERAUTH_INFO_REQUEST msg"); leave_function(); return SSH_AUTH_ERROR; } string_free(tmp); if (session->kbdint == NULL) { session->kbdint = kbdint_new(); if (session->kbdint == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); string_free(name); string_free(instruction); leave_function(); return SSH_AUTH_ERROR; } } else { kbdint_clean(session->kbdint); } session->kbdint->name = string_to_char(name); string_free(name); if (session->kbdint->name == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); kbdint_free(session->kbdint); leave_function(); return SSH_AUTH_ERROR; } session->kbdint->instruction = string_to_char(instruction); string_free(instruction); if (session->kbdint->instruction == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); kbdint_free(session->kbdint); session->kbdint = NULL; leave_function(); return SSH_AUTH_ERROR; } nprompts = ntohl(nprompts); if (nprompts > KBDINT_MAX_PROMPT) { ssh_set_error(session, SSH_FATAL, "Too much prompt asked from server: %u (0x%.4x)", nprompts, nprompts); kbdint_free(session->kbdint); session->kbdint = NULL; leave_function(); return SSH_AUTH_ERROR; } session->kbdint->nprompts = nprompts; session->kbdint->prompts = malloc(nprompts * sizeof(char *)); if (session->kbdint->prompts == NULL) { session->kbdint->nprompts = 0; ssh_set_error(session, SSH_FATAL, "No space left"); kbdint_free(session->kbdint); session->kbdint = NULL; leave_function(); return SSH_AUTH_ERROR; } memset(session->kbdint->prompts, 0, nprompts * sizeof(char *)); session->kbdint->echo = malloc(nprompts); if (session->kbdint->echo == NULL) { session->kbdint->nprompts = 0; ssh_set_error(session, SSH_FATAL, "No space left"); kbdint_free(session->kbdint); session->kbdint = NULL; leave_function(); return SSH_AUTH_ERROR; } memset(session->kbdint->echo, 0, nprompts); for (i = 0; i < nprompts; i++) { tmp = buffer_get_ssh_string(session->in_buffer); buffer_get_u8(session->in_buffer, &session->kbdint->echo[i]); if (tmp == NULL) { ssh_set_error(session, SSH_FATAL, "Short INFO_REQUEST packet"); kbdint_free(session->kbdint); session->kbdint = NULL; leave_function(); return SSH_AUTH_ERROR; } session->kbdint->prompts[i] = string_to_char(tmp); string_free(tmp); if (session->kbdint->prompts[i] == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); kbdint_free(session->kbdint); session->kbdint = NULL; leave_function(); return SSH_AUTH_ERROR; } } leave_function(); return SSH_AUTH_INFO; /* we are not auth. but we parsed the packet */ }
void PhysXForceField::setName(const core::string& name) { m_name=name; m_forceField->setName(string_to_char(name).c_str()); }
SFTP_CLIENT_MESSAGE *sftp_get_client_message(SFTP_SESSION *sftp) { SFTP_PACKET *packet=sftp_packet_read(sftp); SFTP_CLIENT_MESSAGE *msg=malloc(sizeof (SFTP_CLIENT_MESSAGE)); BUFFER *payload; STRING *tmp; memset(msg,0,sizeof(SFTP_CLIENT_MESSAGE)); if(!packet) return NULL; payload=packet->payload; ssh_say(2,"received sftp packet type %d\n",packet->type); msg->type=packet->type; msg->sftp=sftp; buffer_get_u32(payload,&msg->id); switch(msg->type) { case SSH_FXP_CLOSE: case SSH_FXP_READDIR: msg->handle=buffer_get_ssh_string(payload); break; case SSH_FXP_READ: msg->handle=buffer_get_ssh_string(payload); buffer_get_u64(payload,&msg->offset); buffer_get_u32(payload,&msg->len); break; case SSH_FXP_WRITE: msg->handle=buffer_get_ssh_string(payload); buffer_get_u64(payload,&msg->offset); msg->data=buffer_get_ssh_string(payload); break; case SSH_FXP_REMOVE: case SSH_FXP_RMDIR: case SSH_FXP_OPENDIR: case SSH_FXP_READLINK: case SSH_FXP_REALPATH: tmp=buffer_get_ssh_string(payload); msg->filename=string_to_char(tmp); free(tmp); break; case SSH_FXP_RENAME: case SSH_FXP_SYMLINK: tmp=buffer_get_ssh_string(payload); msg->filename=string_to_char(tmp); free(tmp); msg->data=buffer_get_ssh_string(payload); break; case SSH_FXP_MKDIR: case SSH_FXP_SETSTAT: tmp=buffer_get_ssh_string(payload); msg->filename=string_to_char(tmp); free(tmp); msg->attr=sftp_parse_attr(sftp, payload,0); break; case SSH_FXP_FSETSTAT: msg->handle=buffer_get_ssh_string(payload); msg->attr=sftp_parse_attr(sftp, payload,0); break; case SSH_FXP_LSTAT: case SSH_FXP_STAT: tmp=buffer_get_ssh_string(payload); msg->filename=string_to_char(tmp); free(tmp); if(sftp->version >3) buffer_get_u32(payload,&msg->flags); break; case SSH_FXP_OPEN: tmp=buffer_get_ssh_string(payload); msg->filename=string_to_char(tmp); free(tmp); buffer_get_u32(payload,&msg->flags); msg->attr=sftp_parse_attr(sftp, payload,0); case SSH_FXP_FSTAT: msg->handle=buffer_get_ssh_string(payload); buffer_get_u32(payload,&msg->flags); break; default: printf("Received handled sftp message %d\n",msg->type); } msg->flags=ntohl(msg->flags); msg->offset=ntohll(msg->offset); msg->len=ntohl(msg->len); sftp_packet_free(packet); return msg; }
void packet_parse(SSH_SESSION *session) { STRING *error_s = NULL; char *error = NULL; int type = session->in_packet.type; u32 tmp; #ifdef HAVE_SSH1 if (session->version == 1) { /* SSH-1 */ switch(type) { case SSH_MSG_DISCONNECT: ssh_log(session, SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT"); ssh_set_error(session, SSH_FATAL, "Received SSH_MSG_DISCONNECT"); ssh_socket_close(session->socket); session->alive = 0; return; case SSH_SMSG_STDOUT_DATA: case SSH_SMSG_STDERR_DATA: case SSH_SMSG_EXITSTATUS: channel_handle1(session,type); return; case SSH_MSG_DEBUG: case SSH_MSG_IGNORE: break; default: ssh_log(session, SSH_LOG_PACKET, "Unexpected message code %d", type); } return; } else { #endif /* HAVE_SSH1 */ switch(type) { case SSH2_MSG_DISCONNECT: buffer_get_u32(session->in_buffer, &tmp); error_s = buffer_get_ssh_string(session->in_buffer); if (error_s == NULL) { return; } error = string_to_char(error_s); string_free(error_s); if (error == NULL) { return; } ssh_log(session, SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT\n"); ssh_set_error(session, SSH_FATAL, "Received SSH_MSG_DISCONNECT: %s",error); SAFE_FREE(error); ssh_socket_close(session->socket); session->alive = 0; return; case SSH2_MSG_CHANNEL_WINDOW_ADJUST: case SSH2_MSG_CHANNEL_DATA: case SSH2_MSG_CHANNEL_EXTENDED_DATA: case SSH2_MSG_CHANNEL_REQUEST: case SSH2_MSG_CHANNEL_EOF: case SSH2_MSG_CHANNEL_CLOSE: channel_handle(session,type); case SSH2_MSG_IGNORE: case SSH2_MSG_DEBUG: return; default: ssh_log(session, SSH_LOG_RARE, "Received unhandled packet %d", type); } #ifdef HAVE_SSH1 } #endif }