/** @brief Select the different methods on basis of client's and * server's kex messages, and watches out if a match is possible. */ int ssh_kex_select_methods (ssh_session session){ struct ssh_kex_struct *server = &session->next_crypto->server_kex; struct ssh_kex_struct *client = &session->next_crypto->client_kex; int i; for (i = 0; i < KEX_METHODS_SIZE; i++) { session->next_crypto->kex_methods[i]=ssh_find_matching(server->methods[i],client->methods[i]); if(session->next_crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S){ ssh_set_error(session,SSH_FATAL,"kex error : no match for method %s: server [%s], client [%s]", ssh_kex_descriptions[i],server->methods[i],client->methods[i]); return SSH_ERROR; } else if ((i >= SSH_LANG_C_S) && (session->next_crypto->kex_methods[i] == NULL)) { /* we can safely do that for languages */ session->next_crypto->kex_methods[i] = strdup(""); } } if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group1-sha1") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GROUP1_SHA1; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha1") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA1; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){ session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP256; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "*****@*****.**") == 0){ session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG; } return SSH_OK; }
int set_kex(SSH_SESSION *session){ KEX *server = &session->server_kex; KEX *client=&session->client_kex; SSH_OPTIONS *options=session->options; int i; char *wanted; /* the client might ask for a specific cookie to be sent. useful for server debugging */ if(options->wanted_cookie) memcpy(client->cookie,options->wanted_cookie,16); else ssh_get_random(client->cookie,16,0); client->methods=malloc(10 * sizeof(char **)); memset(client->methods,0,10*sizeof(char **)); for (i=0;i<10;i++){ if(!(wanted=options->wanted_methods[i])) wanted=default_methods[i]; client->methods[i]=ssh_find_matching(server->methods[i],wanted); if(!client->methods[i] && i < SSH_LANG_C_S){ ssh_set_error(session,SSH_FATAL,"kex error : did not find one of algos %s in list %s for %s", wanted,server->methods[i],ssh_kex_nums[i]); return -1; } else { if(i>=SSH_LANG_C_S && !client->methods[i]) client->methods[i]=strdup(""); // we can safely do that for languages } } return 0; }
/* returns 1 if at least one of the name algos is in the default algorithms table */ int ssh_verify_existing_algo(int algo, const char *name){ char *ptr; if(algo>9 || algo <0) return -1; ptr=ssh_find_matching(supported_methods[algo],name); if(ptr){ free(ptr); return 1; } return 0; }
/* returns 1 if at least one of the name algos is in the default algorithms table */ int ssh_verify_existing_algo(enum ssh_kex_types_e algo, const char *name) { char *ptr; if (algo > SSH_LANG_S_C) { return -1; } ptr=ssh_find_matching(supported_methods[algo],name); if(ptr){ free(ptr); return 1; } return 0; }
int set_kex(ssh_session session){ KEX *server = &session->server_kex; KEX *client=&session->client_kex; int i; const char *wanted; enter_function(); ssh_get_random(client->cookie,16,0); client->methods=malloc(10 * sizeof(char **)); if (client->methods == NULL) { ssh_set_error(session, SSH_FATAL, "No space left"); leave_function(); return -1; } memset(client->methods,0,10*sizeof(char **)); for (i=0;i<10;i++){ if(!(wanted=session->wanted_methods[i])) wanted=default_methods[i]; client->methods[i]=ssh_find_matching(server->methods[i],wanted); if(!client->methods[i] && i < SSH_LANG_C_S){ ssh_set_error(session,SSH_FATAL,"kex error : did not find one of algos %s in list %s for %s", wanted,server->methods[i],ssh_kex_nums[i]); leave_function(); return -1; } else { if ((i >= SSH_LANG_C_S) && (client->methods[i] == NULL)) { /* we can safely do that for languages */ client->methods[i] = strdup(""); if (client->methods[i] == NULL) { return -1; } } } } leave_function(); return 0; }
// TODO Obviously too much cut and paste here int crypt_set_algorithms_server(SSH_SESSION *session){ char *server = NULL; char *client = NULL; char *match = NULL; int i = 0; /* we must scan the kex entries to find crypto algorithms and set their appropriate structure */ enter_function(); /* out */ server = session->server_kex.methods[SSH_CRYPT_S_C]; client = session->client_kex.methods[SSH_CRYPT_S_C]; match = ssh_find_matching(client,server); if(!match){ ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no matching algorithm function found for %s",server); free(match); leave_function(); return SSH_ERROR; } while(ssh_ciphertab[i].name && strcmp(match,ssh_ciphertab[i].name)) i++; if(!ssh_ciphertab[i].name){ ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no crypto algorithm function found for %s",server); free(match); leave_function(); return SSH_ERROR; } ssh_log(session,SSH_LOG_PACKET,"Set output algorithm %s",match); SAFE_FREE(match); session->next_crypto->out_cipher = cipher_new(i); if (session->next_crypto->out_cipher == NULL) { ssh_set_error(session, SSH_FATAL, "No space left"); leave_function(); return SSH_ERROR; } i=0; /* in */ client=session->client_kex.methods[SSH_CRYPT_C_S]; server=session->server_kex.methods[SSH_CRYPT_S_C]; match=ssh_find_matching(client,server); if(!match){ ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no matching algorithm function found for %s",server); free(match); leave_function(); return SSH_ERROR; } while(ssh_ciphertab[i].name && strcmp(match,ssh_ciphertab[i].name)) i++; if(!ssh_ciphertab[i].name){ ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no crypto algorithm function found for %s",server); free(match); leave_function(); return SSH_ERROR; } ssh_log(session,SSH_LOG_PACKET,"Set input algorithm %s",match); SAFE_FREE(match); session->next_crypto->in_cipher = cipher_new(i); if (session->next_crypto->in_cipher == NULL) { ssh_set_error(session, SSH_FATAL, "No space left"); leave_function(); return SSH_ERROR; } /* compression */ client=session->client_kex.methods[SSH_CRYPT_C_S]; server=session->server_kex.methods[SSH_CRYPT_C_S]; match=ssh_find_matching(client,server); if(match && !strcmp(match,"zlib")){ ssh_log(session,SSH_LOG_PACKET,"enabling C->S compression"); session->next_crypto->do_compress_in=1; } free(match); client=session->client_kex.methods[SSH_CRYPT_S_C]; server=session->server_kex.methods[SSH_CRYPT_S_C]; match=ssh_find_matching(client,server); if(match && !strcmp(match,"zlib")){ ssh_log(session,SSH_LOG_PACKET,"enabling S->C compression\n"); session->next_crypto->do_compress_out=1; } free(match); server=session->server_kex.methods[SSH_HOSTKEYS]; client=session->client_kex.methods[SSH_HOSTKEYS]; match=ssh_find_matching(client,server); if(!strcmp(match,"ssh-dss")) session->hostkeys=TYPE_DSS; else if(!strcmp(match,"ssh-rsa")) session->hostkeys=TYPE_RSA; else { ssh_set_error(session,SSH_FATAL,"cannot know what %s is into %s",match,server); free(match); leave_function(); return SSH_ERROR; } free(match); leave_function(); return SSH_OK; }
/** @brief Select the different methods on basis of client's and * server's kex messages, and watches out if a match is possible. */ int ssh_kex_select_methods (ssh_session session){ struct ssh_kex_struct *server = &session->next_crypto->server_kex; struct ssh_kex_struct *client = &session->next_crypto->client_kex; char *ext_start = NULL; int i; /* Here we should drop the ext-info-c from the list so we avoid matching. * it. We added it to the end, so we can just truncate the string here */ ext_start = strstr(client->methods[SSH_KEX], ","KEX_EXTENSION_CLIENT); if (ext_start != NULL) { ext_start[0] = '\0'; } for (i = 0; i < KEX_METHODS_SIZE; i++) { session->next_crypto->kex_methods[i]=ssh_find_matching(server->methods[i],client->methods[i]); if(session->next_crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S){ ssh_set_error(session,SSH_FATAL,"kex error : no match for method %s: server [%s], client [%s]", ssh_kex_descriptions[i],server->methods[i],client->methods[i]); return SSH_ERROR; } else if ((i >= SSH_LANG_C_S) && (session->next_crypto->kex_methods[i] == NULL)) { /* we can safely do that for languages */ session->next_crypto->kex_methods[i] = strdup(""); } } if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group1-sha1") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GROUP1_SHA1; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha1") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA1; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group16-sha512") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GROUP16_SHA512; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group18-sha512") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GROUP18_SHA512; #ifdef WITH_GEX } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha1") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GEX_SHA1; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha256") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GEX_SHA256; #endif /* WITH_GEX */ } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){ session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP256; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp384") == 0){ session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP384; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp521") == 0){ session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP521; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "*****@*****.**") == 0){ session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256") == 0){ session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256; } SSH_LOG(SSH_LOG_INFO, "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s", session->next_crypto->kex_methods[SSH_KEX], session->next_crypto->kex_methods[SSH_HOSTKEYS], session->next_crypto->kex_methods[SSH_CRYPT_C_S], session->next_crypto->kex_methods[SSH_CRYPT_S_C], session->next_crypto->kex_methods[SSH_MAC_C_S], session->next_crypto->kex_methods[SSH_MAC_S_C], session->next_crypto->kex_methods[SSH_COMP_C_S], session->next_crypto->kex_methods[SSH_COMP_S_C], session->next_crypto->kex_methods[SSH_LANG_C_S], session->next_crypto->kex_methods[SSH_LANG_S_C] ); return SSH_OK; }