static int server_set_kex(ssh_session session) { struct ssh_kex_struct *server = &session->next_crypto->server_kex; int i, j, rc; const char *wanted; char hostkeys[64] = {0}; enum ssh_keytypes_e keytype; size_t len; ZERO_STRUCTP(server); ssh_get_random(server->cookie, 16, 0); #ifdef HAVE_ECC if (session->srv.ecdsa_key != NULL) { snprintf(hostkeys, sizeof(hostkeys), "%s", session->srv.ecdsa_key->type_c); } #endif if (session->srv.dsa_key != NULL) { len = strlen(hostkeys); keytype = ssh_key_type(session->srv.dsa_key); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",%s", ssh_key_type_to_char(keytype)); } if (session->srv.rsa_key != NULL) { len = strlen(hostkeys); keytype = ssh_key_type(session->srv.rsa_key); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",%s", ssh_key_type_to_char(keytype)); } if (strlen(hostkeys) == 0) { return -1; } rc = ssh_options_set_algo(session, SSH_HOSTKEYS, hostkeys[0] == ',' ? hostkeys + 1 : hostkeys); if (rc < 0) { return -1; } for (i = 0; i < 10; i++) { if ((wanted = session->opts.wanted_methods[i]) == NULL) { wanted = ssh_kex_get_supported_method(i); } server->methods[i] = strdup(wanted); if (server->methods[i] == NULL) { for (j = 0; j < i; j++) { SAFE_FREE(server->methods[j]); } return -1; } } return 0; }
static int pkd_auth_pubkey_cb(ssh_session s, const char *user, ssh_key key, char state, void *userdata) { (void) s; (void) user; (void) key; (void) state; (void) userdata; pkdout("pkd_auth_pubkey_cb keytype %s, state: %d\n", ssh_key_type_to_char(ssh_key_type(key)), state); if ((state == SSH_PUBLICKEY_STATE_NONE) || (state == SSH_PUBLICKEY_STATE_VALID)) { return SSH_AUTH_SUCCESS; } return SSH_AUTH_DENIED; }
static void torture_pki_keytype(void **state) { enum ssh_keytypes_e type; const char *type_c; (void) state; /* unused */ type = ssh_key_type(NULL); assert_true(type == SSH_KEYTYPE_UNKNOWN); type = ssh_key_type_from_name(NULL); assert_true(type == SSH_KEYTYPE_UNKNOWN); type = ssh_key_type_from_name("42"); assert_true(type == SSH_KEYTYPE_UNKNOWN); type_c = ssh_key_type_to_char(SSH_KEYTYPE_UNKNOWN); assert_true(type_c == NULL); type_c = ssh_key_type_to_char(42); assert_true(type_c == NULL); }
static void torture_pki_import_privkey_base64_RSA(void **state) { int rc; char *key_str; ssh_key key; const char *passphrase = LIBSSH_PASSPHRASE; enum ssh_keytypes_e type; (void) state; /* unused */ key_str = read_file(LIBSSH_RSA_TESTKEY); assert_true(key_str != NULL); rc = ssh_pki_import_privkey_base64(key_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_RSA); rc = ssh_key_is_public(key); assert_true(rc == 1); free(key_str); ssh_key_free(key); }
static int ssh_bind_import_keys(ssh_bind sshbind) { int rc; if (sshbind->ecdsakey == NULL && sshbind->dsakey == NULL && sshbind->rsakey == NULL) { ssh_set_error(sshbind, SSH_FATAL, "ECDSA, DSA, or RSA host key file must be set"); return SSH_ERROR; } #ifdef HAVE_ECC if (sshbind->ecdsa == NULL && sshbind->ecdsakey != NULL) { rc = ssh_pki_import_privkey_file(sshbind->ecdsakey, NULL, NULL, NULL, &sshbind->ecdsa); if (rc == SSH_ERROR || rc == SSH_EOF) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private ECDSA host key"); return SSH_ERROR; } if (ssh_key_type(sshbind->ecdsa) != SSH_KEYTYPE_ECDSA) { ssh_set_error(sshbind, SSH_FATAL, "The ECDSA host key has the wrong type"); ssh_key_free(sshbind->ecdsa); sshbind->ecdsa = NULL; return SSH_ERROR; } } #endif if (sshbind->dsa == NULL && sshbind->dsakey != NULL) { rc = ssh_pki_import_privkey_file(sshbind->dsakey, NULL, NULL, NULL, &sshbind->dsa); if (rc == SSH_ERROR || rc == SSH_EOF) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private DSA host key"); return SSH_ERROR; } if (ssh_key_type(sshbind->dsa) != SSH_KEYTYPE_DSS) { ssh_set_error(sshbind, SSH_FATAL, "The DSA host key has the wrong type: %d", ssh_key_type(sshbind->dsa)); ssh_key_free(sshbind->dsa); sshbind->dsa = NULL; return SSH_ERROR; } } if (sshbind->rsa == NULL && sshbind->rsakey != NULL) { rc = ssh_pki_import_privkey_file(sshbind->rsakey, NULL, NULL, NULL, &sshbind->rsa); if (rc == SSH_ERROR || rc == SSH_EOF) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private RSA host key"); return SSH_ERROR; } if (ssh_key_type(sshbind->rsa) != SSH_KEYTYPE_RSA && ssh_key_type(sshbind->rsa) != SSH_KEYTYPE_RSA1) { ssh_set_error(sshbind, SSH_FATAL, "The RSA host key has the wrong type"); ssh_key_free(sshbind->rsa); sshbind->rsa = NULL; return SSH_ERROR; } } return SSH_OK; }
static char * key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k) { /* * Chars to be used after each other every time the worm * intersects with itself. Matter of taste. */ char *augmentation_string = " .o+=*BOX@%&#/^SE"; char *retval, *p; unsigned char field[FLDSIZE_X][FLDSIZE_Y]; unsigned int i, b; int x, y; size_t len = strlen(augmentation_string) - 1; retval = calloc(1, (FLDSIZE_X + 3 + 1) * (FLDSIZE_Y + 2)); /* initialize field */ memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char)); x = FLDSIZE_X / 2; y = FLDSIZE_Y / 2; /* process raw key */ for (i = 0; i < dgst_raw_len; i++) { int input; /* each byte conveys four 2-bit move commands */ input = dgst_raw[i]; for (b = 0; b < 4; b++) { /* evaluate 2 bit, rest is shifted later */ x += (input & 0x1) ? 1 : -1; y += (input & 0x2) ? 1 : -1; /* assure we are still in bounds */ x = max(x, 0); y = max(y, 0); x = min(x, FLDSIZE_X - 1); y = min(y, FLDSIZE_Y - 1); /* augment the field */ field[x][y]++; input = input >> 2; } } /* mark starting point and end point*/ field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1; field[x][y] = len; /* fill in retval */ _snprintf_s(retval, FLDSIZE_X, _TRUNCATE, "+--[%4s %4u]", ssh_key_type(k->type), key_size(k)); p = strchr(retval, '\0'); /* output upper border */ for (i = p - retval - 1; i < FLDSIZE_X; i++) *p++ = '-'; *p++ = '+'; *p++ = '\r'; *p++ = '\n'; /* output content */ for (y = 0; y < FLDSIZE_Y; y++) { *p++ = '|'; for (x = 0; x < FLDSIZE_X; x++) *p++ = augmentation_string[min(field[x][y], len)]; *p++ = '|'; *p++ = '\r'; *p++ = '\n'; } /* output lower border */ *p++ = '+'; for (i = 0; i < FLDSIZE_X; i++) *p++ = '-'; *p++ = '+'; return retval; }
static const gchar * verify_knownhost (CockpitSshData *data) { const gchar *ret = "unknown-hostkey"; ssh_key key = NULL; unsigned char *hash = NULL; const char *type = NULL; int state; gsize len; data->host_key = get_knownhosts_line (data->session); if (data->host_key == NULL) { ret = "internal-error"; goto done; } if (ssh_get_publickey (data->session, &key) != SSH_OK) { g_warning ("Couldn't look up ssh host key"); ret = "internal-error"; goto done; } type = ssh_key_type_to_char (ssh_key_type (key)); if (type == NULL) { g_warning ("Couldn't lookup host key type"); ret = "internal-error"; goto done; } if (ssh_get_publickey_hash (key, SSH_PUBLICKEY_HASH_MD5, &hash, &len) < 0) { g_warning ("Couldn't hash ssh public key"); ret = "internal-error"; goto done; } else { data->host_fingerprint = ssh_get_hexa (hash, len); ssh_clean_pubkey_hash (&hash); } if (data->expect_key) { /* Only check that the host key matches this specifically */ if (g_str_equal (data->host_key, data->expect_key)) { g_debug ("%s: host key matched expected", data->logname); ret = NULL; /* success */ } else { /* A empty expect_key is used by the frontend to force failure. Don't warn about it. */ if (data->expect_key[0]) g_message ("%s: host key did not match expected", data->logname); } } else { if (ssh_options_set (data->session, SSH_OPTIONS_KNOWNHOSTS, data->knownhosts_file) != SSH_OK) { g_warning ("Couldn't set knownhosts file location"); ret = "internal-error"; goto done; } state = ssh_is_server_known (data->session); if (state == SSH_SERVER_KNOWN_OK) { g_debug ("%s: verified host key", data->logname); ret = NULL; /* success */ goto done; } else if (state == SSH_SERVER_ERROR) { if (g_atomic_int_get (data->connecting)) g_warning ("%s: couldn't check host key: %s", data->logname, ssh_get_error (data->session)); ret = "internal-error"; goto done; } switch (state) { case SSH_SERVER_KNOWN_OK: case SSH_SERVER_ERROR: g_assert_not_reached (); break; case SSH_SERVER_KNOWN_CHANGED: g_message ("%s: %s host key for server has changed to: %s", data->logname, type, data->host_fingerprint); break; case SSH_SERVER_FOUND_OTHER: g_message ("%s: host key for this server changed key type: %s", data->logname, type); break; case SSH_SERVER_FILE_NOT_FOUND: g_debug ("Couldn't find the known hosts file"); /* fall through */ case SSH_SERVER_NOT_KNOWN: g_message ("%s: %s host key for server is not known: %s", data->logname, type, data->host_fingerprint); break; } } done: if (key) ssh_key_free (key); return ret; }
int ssh_bind_listen(ssh_bind sshbind) { const char *host; socket_t fd; int rc; if (ssh_init() < 0) { ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed"); return -1; } if (sshbind->dsakey == NULL && sshbind->rsakey == NULL) { ssh_set_error(sshbind, SSH_FATAL, "DSA or RSA host key file must be set before listen()"); return SSH_ERROR; } if (sshbind->dsakey) { rc = ssh_pki_import_privkey_file(sshbind->dsakey, NULL, NULL, NULL, &sshbind->dsa); if (rc == SSH_ERROR) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private DSA host key"); return SSH_ERROR; } if (ssh_key_type(sshbind->dsa) != SSH_KEYTYPE_DSS) { ssh_set_error(sshbind, SSH_FATAL, "The DSA host key has the wrong type"); ssh_key_free(sshbind->dsa); return SSH_ERROR; } } if (sshbind->rsakey) { rc = ssh_pki_import_privkey_file(sshbind->rsakey, NULL, NULL, NULL, &sshbind->rsa); if (rc == SSH_ERROR) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private RSA host key"); return SSH_ERROR; } if (ssh_key_type(sshbind->rsa) != SSH_KEYTYPE_RSA && ssh_key_type(sshbind->rsa) != SSH_KEYTYPE_RSA1) { ssh_set_error(sshbind, SSH_FATAL, "The RSA host key has the wrong type"); ssh_key_free(sshbind->rsa); return SSH_ERROR; } } if (sshbind->bindfd == SSH_INVALID_SOCKET) { host = sshbind->bindaddr; if (host == NULL) { host = "0.0.0.0"; } fd = bind_socket(sshbind, host, sshbind->bindport); if (fd == SSH_INVALID_SOCKET) { ssh_key_free(sshbind->dsa); ssh_key_free(sshbind->rsa); return -1; } sshbind->bindfd = fd; if (listen(fd, 10) < 0) { ssh_set_error(sshbind, SSH_FATAL, "Listening to socket %d: %s", fd, strerror(errno)); close(fd); ssh_key_free(sshbind->dsa); ssh_key_free(sshbind->rsa); return -1; } } else { SSH_LOG(sshbind, SSH_LOG_INFO, "Using app-provided bind socket"); } return 0; }
int server_set_kex(ssh_session session) { struct ssh_kex_struct *server = &session->next_crypto->server_kex; int i, j, rc; const char *wanted; char hostkeys[128] = {0}; enum ssh_keytypes_e keytype; size_t len; int ok; ZERO_STRUCTP(server); ok = ssh_get_random(server->cookie, 16, 0); if (!ok) { ssh_set_error(session, SSH_FATAL, "PRNG error"); return -1; } if (session->srv.ed25519_key != NULL) { snprintf(hostkeys, sizeof(hostkeys), "%s", ssh_key_type_to_char(ssh_key_type(session->srv.ed25519_key))); } #ifdef HAVE_ECC if (session->srv.ecdsa_key != NULL) { len = strlen(hostkeys); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",%s", session->srv.ecdsa_key->type_c); } #endif #ifdef HAVE_DSA if (session->srv.dsa_key != NULL) { len = strlen(hostkeys); keytype = ssh_key_type(session->srv.dsa_key); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",%s", ssh_key_type_to_char(keytype)); } #endif if (session->srv.rsa_key != NULL) { /* We support also the SHA2 variants */ len = strlen(hostkeys); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",rsa-sha2-512,rsa-sha2-256"); len = strlen(hostkeys); keytype = ssh_key_type(session->srv.rsa_key); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",%s", ssh_key_type_to_char(keytype)); } if (strlen(hostkeys) == 0) { return -1; } rc = ssh_options_set_algo(session, SSH_HOSTKEYS, hostkeys[0] == ',' ? hostkeys + 1 : hostkeys); if (rc < 0) { return -1; } for (i = 0; i < 10; i++) { if ((wanted = session->opts.wanted_methods[i]) == NULL) { wanted = ssh_kex_get_supported_method(i); } server->methods[i] = strdup(wanted); if (server->methods[i] == NULL) { for (j = 0; j < i; j++) { SAFE_FREE(server->methods[j]); } return -1; } } return 0; }