/* * This function concats in a buffer the values needed to do a signature * verification. */ ssh_buffer ssh_userauth_build_digest(ssh_session session, ssh_message msg, char *service) { /* The value of 'signature' is a signature by the corresponding private key over the following data, in the following order: string session identifier byte SSH_MSG_USERAUTH_REQUEST string user name string service name string "publickey" boolean TRUE string public key algorithm name string public key to be used for authentication */ struct ssh_crypto_struct *crypto = session->current_crypto ? session->current_crypto : session->next_crypto; ssh_buffer buffer = NULL; ssh_string session_id = NULL; uint8_t type = SSH2_MSG_USERAUTH_REQUEST; ssh_string username = ssh_string_from_char(msg->auth_request.username); ssh_string servicename = ssh_string_from_char(service); ssh_string method = ssh_string_from_char("publickey"); uint8_t has_sign = 1; ssh_string algo = ssh_string_from_char(msg->auth_request.public_key->type_c); ssh_string publickey = publickey_to_string(msg->auth_request.public_key); buffer = ssh_buffer_new(); if (buffer == NULL) { goto error; } session_id = ssh_string_new(SHA_DIGEST_LEN); if (session_id == NULL) { ssh_buffer_free(buffer); buffer = NULL; goto error; } ssh_string_fill(session_id, crypto->session_id, SHA_DIGEST_LEN); if(buffer_add_ssh_string(buffer, session_id) < 0 || buffer_add_u8(buffer, type) < 0 || buffer_add_ssh_string(buffer, username) < 0 || buffer_add_ssh_string(buffer, servicename) < 0 || buffer_add_ssh_string(buffer, method) < 0 || buffer_add_u8(buffer, has_sign) < 0 || buffer_add_ssh_string(buffer, algo) < 0 || buffer_add_ssh_string(buffer, publickey) < 0) { ssh_buffer_free(buffer); buffer = NULL; goto error; } error: if(session_id) ssh_string_free(session_id); if(username) ssh_string_free(username); if(servicename) ssh_string_free(servicename); if(method) ssh_string_free(method); if(algo) ssh_string_free(algo); if(publickey) ssh_string_free(publickey); return buffer; }
static int ssh_gssapi_send_auth_mic(ssh_session session, ssh_string *oid_set, int n_oid){ ssh_string str; int rc; int i; rc = buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_REQUEST); if (rc < 0) { goto fail; } /* username */ str = ssh_string_from_char(session->opts.username); if (str == NULL) { goto fail; } rc = buffer_add_ssh_string(session->out_buffer, str); ssh_string_free(str); if (rc < 0) { goto fail; } /* service */ str = ssh_string_from_char("ssh-connection"); if (str == NULL) { goto fail; } rc = buffer_add_ssh_string(session->out_buffer, str); ssh_string_free(str); if (rc < 0) { goto fail; } /* method */ str = ssh_string_from_char("gssapi-with-mic"); if (str == NULL) { goto fail; } rc = buffer_add_ssh_string(session->out_buffer, str); ssh_string_free(str); if (rc < 0) { goto fail; } rc = buffer_add_u32(session->out_buffer, htonl(n_oid)); if (rc < 0) { goto fail; } for (i=0; i<n_oid; ++i){ rc = buffer_add_ssh_string(session->out_buffer, oid_set[i]); if (rc < 0) { goto fail; } } session->auth_state = SSH_AUTH_STATE_GSSAPI_REQUEST_SENT; return packet_send(session); fail: buffer_reinit(session->out_buffer); return SSH_ERROR; }
int sftp_reply_status(sftp_client_message msg, uint32_t status, const char *message) { ssh_buffer out; ssh_string s; out = ssh_buffer_new(); if (out == NULL) { return -1; } s = ssh_string_from_char(message ? message : ""); if (s == NULL) { ssh_buffer_free(out); return -1; } if (ssh_buffer_add_u32(out, msg->id) < 0 || ssh_buffer_add_u32(out, htonl(status)) < 0 || ssh_buffer_add_ssh_string(out, s) < 0 || ssh_buffer_add_u32(out, 0) < 0 || /* language string */ sftp_packet_write(msg->sftp, SSH_FXP_STATUS, out) < 0) { ssh_buffer_free(out); ssh_string_free(s); return -1; } ssh_buffer_free(out); ssh_string_free(s); return 0; }
int ssh_send_keepalive(ssh_session session) { /* TODO check the reply and all that */ struct ssh_string_struct *req; int reply = 1; int rc = SSH_ERROR; enter_function(); req = ssh_string_from_char("*****@*****.**"); if (req == NULL) { ssh_set_error_oom(session); goto out; } if (buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST) < 0 || buffer_add_ssh_string(session->out_buffer, req) < 0 || buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1) < 0) { ssh_set_error_oom(session); goto out; } if (packet_send(session) == SSH_ERROR) goto out; ssh_handle_packets(session, 0); ssh_log(session, SSH_LOG_PACKET, "Sent a keepalive"); rc = SSH_OK; out: ssh_string_free(req); leave_function(); return rc; }
int ssh_message_service_reply_success(ssh_message msg) { struct ssh_string_struct *service; ssh_session session; if (msg == NULL) { return SSH_ERROR; } session = msg->session; SSH_LOG(SSH_LOG_PACKET, "Sending a SERVICE_ACCEPT for service %s", msg->service_request.service); if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_ACCEPT) < 0) { return -1; } service=ssh_string_from_char(msg->service_request.service); if (service == NULL) { return -1; } if (buffer_add_ssh_string(session->out_buffer, service) < 0) { ssh_string_free(service); return -1; } ssh_string_free(service); return packet_send(msg->session); }
int channel_request_exec1(ssh_channel channel, const char *cmd) { ssh_session session; ssh_string command = NULL; if (channel == NULL) { return -1; } session = channel->session; command = ssh_string_from_char(cmd); if (command == NULL) { return -1; } if (buffer_add_u8(session->out_buffer, SSH_CMSG_EXEC_CMD) < 0 || buffer_add_ssh_string(session->out_buffer, command) < 0) { ssh_string_free(command); return -1; } ssh_string_free(command); if(packet_send(session) == SSH_ERROR) { return -1; } ssh_log(session, SSH_LOG_RARE, "Executing %s ...", cmd); return 0; }
/* this is a public key in openssh's format */ static ssh_string make_rsa1_string(ssh_string e, ssh_string n){ ssh_buffer buffer = NULL; ssh_string rsa = NULL; ssh_string ret = NULL; buffer = ssh_buffer_new(); rsa = ssh_string_from_char("ssh-rsa1"); if (rsa == NULL) { goto error; } if (ssh_buffer_add_ssh_string(buffer, rsa) < 0) { goto error; } if (ssh_buffer_add_ssh_string(buffer, e) < 0) { goto error; } if (ssh_buffer_add_ssh_string(buffer, n) < 0) { goto error; } ret = ssh_string_new(ssh_buffer_get_len(buffer)); if (ret == NULL) { goto error; } ssh_string_fill(ret, ssh_buffer_get(buffer), ssh_buffer_get_len(buffer)); error: ssh_buffer_free(buffer); ssh_string_free(rsa); return ret; }
static int ssh_message_auth_reply_default(ssh_message msg,int partial) { ssh_session session = msg->session; char methods_c[128] = {0}; ssh_string methods = NULL; int rc = SSH_ERROR; enter_function(); if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_FAILURE) < 0) { return rc; } if (session->auth_methods == 0) { session->auth_methods = SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD; } if (session->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) { strcat(methods_c, "publickey,"); } if (session->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { strcat(methods_c, "keyboard-interactive,"); } if (session->auth_methods & SSH_AUTH_METHOD_PASSWORD) { strcat(methods_c, "password,"); } if (session->auth_methods & SSH_AUTH_METHOD_HOSTBASED) { strcat(methods_c, "hostbased,"); } /* Strip the comma. */ methods_c[strlen(methods_c) - 1] = '\0'; // strip the comma. We are sure there is at ssh_log(session, SSH_LOG_PACKET, "Sending a auth failure. methods that can continue: %s", methods_c); methods = ssh_string_from_char(methods_c); if (methods == NULL) { goto error; } if (buffer_add_ssh_string(msg->session->out_buffer, methods) < 0) { goto error; } if (partial) { if (buffer_add_u8(session->out_buffer, 1) < 0) { goto error; } } else { if (buffer_add_u8(session->out_buffer, 0) < 0) { goto error; } } rc = packet_send(msg->session); error: ssh_string_free(methods); leave_function(); return rc; }
int sftp_reply_name(sftp_client_message msg, const char *name, sftp_attributes attr) { ssh_buffer out; ssh_string file; out = ssh_buffer_new(); if (out == NULL) { return -1; } file = ssh_string_from_char(name); if (file == NULL) { ssh_buffer_free(out); return -1; } if (ssh_buffer_add_u32(out, msg->id) < 0 || ssh_buffer_add_u32(out, htonl(1)) < 0 || ssh_buffer_add_ssh_string(out, file) < 0 || ssh_buffer_add_ssh_string(out, file) < 0 || /* The protocol is broken here between 3 & 4 */ buffer_add_attributes(out, attr) < 0 || sftp_packet_write(msg->sftp, SSH_FXP_NAME, out) < 0) { ssh_buffer_free(out); ssh_string_free(file); return -1; } ssh_buffer_free(out); ssh_string_free(file); return 0; }
/* this function only sends the predefined set of kex methods */ int ssh_send_kex(ssh_session session, int server_kex) { struct ssh_kex_struct *kex = (server_kex ? &session->next_crypto->server_kex : &session->next_crypto->client_kex); ssh_string str = NULL; int i; enter_function(); if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXINIT) < 0) { goto error; } if (buffer_add_data(session->out_buffer, kex->cookie, 16) < 0) { goto error; } if (hashbufout_add_cookie(session) < 0) { goto error; } ssh_list_kex(session, kex); for (i = 0; i < KEX_METHODS_SIZE; i++) { str = ssh_string_from_char(kex->methods[i]); if (str == NULL) { goto error; } if (buffer_add_ssh_string(session->out_hashbuf, str) < 0) { goto error; } if (buffer_add_ssh_string(session->out_buffer, str) < 0) { goto error; } ssh_string_free(str); } if (buffer_add_u8(session->out_buffer, 0) < 0) { goto error; } if (buffer_add_u32(session->out_buffer, 0) < 0) { goto error; } if (packet_send(session) == SSH_ERROR) { leave_function(); return -1; } leave_function(); return 0; error: buffer_reinit(session->out_buffer); buffer_reinit(session->out_hashbuf); ssh_string_free(str); leave_function(); return -1; }
/* this function only sends the predefined set of kex methods */ int ssh_send_kex(ssh_session session, int server_kex) { struct ssh_kex_struct *kex = (server_kex ? &session->next_crypto->server_kex : &session->next_crypto->client_kex); ssh_string str = NULL; int i; int rc; rc = ssh_buffer_pack(session->out_buffer, "bP", SSH2_MSG_KEXINIT, 16, kex->cookie); /* cookie */ if (rc != SSH_OK) goto error; if (ssh_hashbufout_add_cookie(session) < 0) { goto error; } ssh_list_kex(kex); for (i = 0; i < KEX_METHODS_SIZE; i++) { str = ssh_string_from_char(kex->methods[i]); if (str == NULL) { goto error; } if (ssh_buffer_add_ssh_string(session->out_hashbuf, str) < 0) { goto error; } if (ssh_buffer_add_ssh_string(session->out_buffer, str) < 0) { goto error; } ssh_string_free(str); str = NULL; } rc = ssh_buffer_pack(session->out_buffer, "bd", 0, 0); if (rc != SSH_OK) { goto error; } if (ssh_packet_send(session) == SSH_ERROR) { return -1; } SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_KEXINIT sent"); return 0; error: ssh_buffer_reinit(session->out_buffer); ssh_buffer_reinit(session->out_hashbuf); ssh_string_free(str); return -1; }
static void *thread_ssh_buffer_add_format(void *threadid) { ssh_buffer buffer = NULL; uint8_t b; uint16_t w; uint32_t d; uint64_t q; ssh_string s = NULL; int rc; size_t len; uint8_t verif[] = "\x42\x13\x37\x0b\xad\xc0\xde\x13\x24\x35\x46" "\xac\xbd\xce\xdf" "\x00\x00\x00\x06" "libssh" "\x00\x00\x00\x05" "rocks" "So much" "Fun!"; /* Unused */ (void) threadid; /* Setup */ buffer = ssh_buffer_new(); if (buffer == NULL) { pthread_exit((void *)-1); } ssh_buffer_set_secure(buffer); b = 0x42; w = 0x1337; d = 0xbadc0de; q = 0x13243546acbdcedf; s = ssh_string_from_char("libssh"); rc = ssh_buffer_pack(buffer, "bwdqSsPt", b, w, d, q, s, "rocks", 7, "So much", "Fun!"); assert_int_equal(rc, SSH_OK); len = ssh_buffer_get_len(buffer); assert_int_equal(len, sizeof(verif) - 1); assert_memory_equal(ssh_buffer_get(buffer), verif, sizeof(verif) -1); SSH_STRING_FREE(s); /* Teardown */ SSH_BUFFER_FREE(buffer); pthread_exit(NULL); }
int ssh_pki_export_signature_blob(const ssh_signature sig, ssh_string *sig_blob) { ssh_buffer buf = NULL; ssh_string str; int rc; if (sig == NULL || sig_blob == NULL) { return SSH_ERROR; } buf = ssh_buffer_new(); if (buf == NULL) { return SSH_ERROR; } str = ssh_string_from_char(sig->type_c); if (str == NULL) { ssh_buffer_free(buf); return SSH_ERROR; } rc = ssh_buffer_add_ssh_string(buf, str); ssh_string_free(str); if (rc < 0) { ssh_buffer_free(buf); return SSH_ERROR; } str = pki_signature_to_blob(sig); if (str == NULL) { ssh_buffer_free(buf); return SSH_ERROR; } rc = ssh_buffer_add_ssh_string(buf, str); ssh_string_free(str); if (rc < 0) { ssh_buffer_free(buf); return SSH_ERROR; } str = ssh_string_new(ssh_buffer_get_len(buf)); if (str == NULL) { ssh_buffer_free(buf); return SSH_ERROR; } ssh_string_fill(str, ssh_buffer_get(buf), ssh_buffer_get_len(buf)); ssh_buffer_free(buf); *sig_blob = str; return SSH_OK; }
int ssh_message_auth_reply_pk_ok_simple(ssh_message msg) { ssh_string algo; ssh_string pubkey; int ret; algo=ssh_string_from_char(msg->auth_request.public_key->type_c); pubkey=publickey_to_string(msg->auth_request.public_key); ret=ssh_message_auth_reply_pk_ok(msg,algo,pubkey); ssh_string_free(algo); ssh_string_free(pubkey); return ret; }
void server_handle_message(ssh_session s, ssh_message m, int type, int subtype, int *state) { int handled = 0; if((*state == SERVER_CONNECTED) && (type == SSH_REQUEST_AUTH) && (subtype == SSH_AUTH_METHOD_PUBLICKEY)) { ssh_public_key key = ssh_message_auth_publickey(m); ssh_string keystr = publickey_to_string(key); char *keyhash = pubkey_hash(keystr); int has_sig = ssh_message_auth_publickey_state(m); if(has_sig == SSH_PUBLICKEY_STATE_NONE) { if(authenticate(keyhash, 1)) { //FIXME: type detection ssh_string algostr = ssh_string_from_char("ssh-rsa"); ssh_message_auth_reply_pk_ok(m, algostr, keystr); handled = 1; ssh_string_free(algostr); } } else if(has_sig == SSH_PUBLICKEY_STATE_VALID) { if(authenticate(keyhash, 0)) { session_event(s, "authenticated", keyhash); ssh_message_auth_reply_success(m, 0); handled = 1; *state = SERVER_AUTHENTICATED; } else { ssh_message_reply_default(m); handled = 1; *state = SERVER_CLOSED; } } ssh_string_free(keystr); free(keyhash); } else if((*state == SERVER_AUTHENTICATED) && (type == SSH_REQUEST_CHANNEL_OPEN) && (subtype == SSH_CHANNEL_SESSION)) { ssh_channel chan = ssh_message_channel_request_open_reply_accept(m); if(!chan) session_error(s, "open-channel"); handled = 1; session_event(s, "channel-opened", NULL); channel_to_file(chan, 1); ssh_channel_free(chan); *state = SERVER_CLOSED; } if(!handled) ssh_message_reply_default(m); }
/** * @internal * * @brief Request a service from the SSH server. * * Service requests are for example: ssh-userauth, ssh-connection, etc. * * @param session The session to use to ask for a service request. * @param service The service request. * * @return SSH_OK on success * @return SSH_ERROR on error * @return SSH_AGAIN No response received yet * @bug actually only works with ssh-userauth */ int ssh_service_request(ssh_session session, const char *service) { ssh_string service_s = NULL; int rc=SSH_ERROR; if(session->auth_service_state != SSH_AUTH_SERVICE_NONE) goto pending; if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_REQUEST) < 0) { return SSH_ERROR; } service_s = ssh_string_from_char(service); if (service_s == NULL) { return SSH_ERROR; } if (buffer_add_ssh_string(session->out_buffer,service_s) < 0) { ssh_string_free(service_s); return SSH_ERROR; } ssh_string_free(service_s); session->auth_service_state=SSH_AUTH_SERVICE_SENT; if (packet_send(session) == SSH_ERROR) { ssh_set_error(session, SSH_FATAL, "Sending SSH2_MSG_SERVICE_REQUEST failed."); return SSH_ERROR; } SSH_LOG(SSH_LOG_PACKET, "Sent SSH_MSG_SERVICE_REQUEST (service %s)", service); pending: rc=ssh_handle_packets_termination(session,SSH_TIMEOUT_USER, ssh_service_request_termination, session); if (rc == SSH_ERROR) { return SSH_ERROR; } switch(session->auth_service_state){ case SSH_AUTH_SERVICE_DENIED: ssh_set_error(session,SSH_FATAL,"ssh_auth_service request denied"); break; case SSH_AUTH_SERVICE_ACCEPTED: rc=SSH_OK; break; case SSH_AUTH_SERVICE_SENT: rc=SSH_AGAIN; break; case SSH_AUTH_SERVICE_NONE: case SSH_AUTH_SERVICE_USER_SENT: /* Invalid state, SSH1 specific */ rc=SSH_ERROR; break; } return rc; }
static int pki_import_cert_buffer(ssh_buffer buffer, enum ssh_keytypes_e type, ssh_key *pkey) { ssh_buffer cert; ssh_string type_s; ssh_key key; int rc; key = ssh_key_new(); if (key == NULL) { return SSH_ERROR; } cert = ssh_buffer_new(); if (cert == NULL) { ssh_key_free(key); return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PUBLIC; /* * The cert blob starts with the key type as an ssh_string, but this * string has been read out of the buffer to identify the key type. * Simply add it again as first element before copying the rest. */ type_s = ssh_string_from_char(key->type_c); if (type_s == NULL) { goto fail; } rc = ssh_buffer_add_ssh_string(cert, type_s); ssh_string_free(type_s); if (rc != 0) { goto fail; } rc = ssh_buffer_add_buffer(cert, buffer); if (rc != 0) { goto fail; } key->cert = (void*) cert; *pkey = key; return SSH_OK; fail: ssh_key_free(key); ssh_buffer_free(cert); return SSH_ERROR; }
static int send_username(ssh_session session, const char *username) { ssh_string user = NULL; /* returns SSH_AUTH_SUCCESS or SSH_AUTH_DENIED */ if(session->auth_service_state == SSH_AUTH_SERVICE_USER_SENT) { if(session->auth_state == SSH_AUTH_STATE_FAILED) return SSH_AUTH_DENIED; if(session->auth_state == SSH_AUTH_STATE_SUCCESS) return SSH_AUTH_SUCCESS; return SSH_AUTH_ERROR; } if (!username) { if(!(username = session->username)) { if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { session->auth_service_state = SSH_AUTH_SERVICE_DENIED; return SSH_ERROR; } else { username = session->username; } } } user = ssh_string_from_char(username); if (user == NULL) { return SSH_AUTH_ERROR; } if (buffer_add_u8(session->out_buffer, SSH_CMSG_USER) < 0) { ssh_string_free(user); return SSH_AUTH_ERROR; } if (buffer_add_ssh_string(session->out_buffer, user) < 0) { ssh_string_free(user); return SSH_AUTH_ERROR; } ssh_string_free(user); session->auth_state=SSH_AUTH_STATE_NONE; if (packet_send(session) == SSH_ERROR) { return SSH_AUTH_ERROR; } if(wait_auth1_status(session) == SSH_AUTH_SUCCESS){ session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT; session->auth_state=SSH_AUTH_STATE_SUCCESS; return SSH_AUTH_SUCCESS; } else { session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT; ssh_set_error(session,SSH_REQUEST_DENIED,"Password authentication necessary for user %s",username); return SSH_AUTH_DENIED; } }
int sftp_reply_names_add(sftp_client_message msg, const char *file, const char *longname, sftp_attributes attr) { ssh_string name; name = ssh_string_from_char(file); if (name == NULL) { return -1; } if (msg->attrbuf == NULL) { msg->attrbuf = ssh_buffer_new(); if (msg->attrbuf == NULL) { ssh_string_free(name); return -1; } } if (ssh_buffer_add_ssh_string(msg->attrbuf, name) < 0) { ssh_string_free(name); return -1; } ssh_string_free(name); name = ssh_string_from_char(longname); if (name == NULL) { return -1; } if (ssh_buffer_add_ssh_string(msg->attrbuf,name) < 0 || buffer_add_attributes(msg->attrbuf,attr) < 0) { ssh_string_free(name); return -1; } ssh_string_free(name); msg->attr_num++; return 0; }
/** * @internal * * @brief Request a service from the SSH server. * * Service requests are for example: ssh-userauth, ssh-connection, etc. * * @param session The session to use to ask for a service request. * @param service The service request. * * @return SSH_OK on success * @return SSH_ERROR on error * @return SSH_AGAIN No response received yet * @bug actually only works with ssh-userauth */ int ssh_service_request(ssh_session session, const char *service) { ssh_string service_s = NULL; int rc=SSH_ERROR; enter_function(); switch(session->auth_service_state){ case SSH_AUTH_SERVICE_NONE: if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_REQUEST) < 0) { break; } service_s = ssh_string_from_char(service); if (service_s == NULL) { break; } if (buffer_add_ssh_string(session->out_buffer,service_s) < 0) { ssh_string_free(service_s); break; } ssh_string_free(service_s); if (packet_send(session) == SSH_ERROR) { ssh_set_error(session, SSH_FATAL, "Sending SSH2_MSG_SERVICE_REQUEST failed."); break; } ssh_log(session, SSH_LOG_PACKET, "Sent SSH_MSG_SERVICE_REQUEST (service %s)", service); session->auth_service_state=SSH_AUTH_SERVICE_SENT; rc=SSH_AGAIN; break; case SSH_AUTH_SERVICE_DENIED: ssh_set_error(session,SSH_FATAL,"ssh_auth_service request denied"); break; case SSH_AUTH_SERVICE_ACCEPTED: rc=SSH_OK; break; case SSH_AUTH_SERVICE_SENT: rc=SSH_AGAIN; break; case SSH_AUTH_SERVICE_USER_SENT: /* Invalid state, SSH1 specific */ rc=SSH_ERROR; break; } leave_function(); return rc; }
/** * @brief Convert a public_key object into a a SSH string. * * @param[in] key The public key to convert. * * @returns An allocated SSH String containing the public key, NULL * on error. * * @see string_free() */ ssh_string publickey_to_string(ssh_public_key key) { ssh_string type = NULL; ssh_string ret = NULL; ssh_buffer buf = NULL; buf = ssh_buffer_new(); if (buf == NULL) { return NULL; } type = ssh_string_from_char(key->type_c); if (type == NULL) { goto error; } if (buffer_add_ssh_string(buf, type) < 0) { goto error; } switch (key->type) { case SSH_KEYTYPE_DSS: if (dsa_public_to_string(key->dsa_pub, buf) < 0) { goto error; } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: if (rsa_public_to_string(key->rsa_pub, buf) < 0) { goto error; } break; } ret = ssh_string_new(buffer_get_rest_len(buf)); if (ret == NULL) { goto error; } ssh_string_fill(ret, buffer_get_rest(buf), buffer_get_rest_len(buf)); error: ssh_buffer_free(buf); if(type != NULL) ssh_string_free(type); return ret; }
int ssh_send_keepalive(ssh_session session) { struct ssh_string_struct *req; int rc; rc = buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST); if (rc < 0) { goto err; } req = ssh_string_from_char("*****@*****.**"); if (req == NULL) { goto err; } rc = buffer_add_ssh_string(session->out_buffer, req); ssh_string_free(req); if (rc < 0) { goto err; } rc = buffer_add_u8(session->out_buffer, 1); if (rc < 0) { goto err; } if (packet_send(session) == SSH_ERROR) { goto err; } ssh_handle_packets(session, 0); SSH_LOG(SSH_LOG_PACKET, "Sent a keepalive"); return SSH_OK; err: ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); return SSH_ERROR; }
int ssh_message_auth_reply_pk_ok_simple(ssh_message msg) { ssh_string algo; ssh_string pubkey_blob = NULL; int ret; algo = ssh_string_from_char(msg->auth_request.pubkey->type_c); if (algo == NULL) { return SSH_ERROR; } ret = ssh_pki_export_pubkey_blob(msg->auth_request.pubkey, &pubkey_blob); if (ret < 0) { ssh_string_free(algo); return SSH_ERROR; } ret = ssh_message_auth_reply_pk_ok(msg, algo, pubkey_blob); ssh_string_free(algo); ssh_string_free(pubkey_blob); return ret; }
/* Signature decoding functions */ ssh_string signature_to_string(SIGNATURE *sign) { unsigned char buffer[40] = {0}; ssh_buffer tmpbuf = NULL; ssh_string str = NULL; ssh_string tmp = NULL; ssh_string rs = NULL; int rc = -1; #ifdef HAVE_LIBGCRYPT const char *r = NULL; const char *s = NULL; gcry_sexp_t sexp; size_t size = 0; #elif defined HAVE_LIBCRYPTO ssh_string r = NULL; ssh_string s = NULL; #endif tmpbuf = ssh_buffer_new(); if (tmpbuf == NULL) { return NULL; } tmp = ssh_string_from_char(ssh_type_to_char(sign->type)); if (tmp == NULL) { ssh_buffer_free(tmpbuf); return NULL; } if (buffer_add_ssh_string(tmpbuf, tmp) < 0) { ssh_buffer_free(tmpbuf); ssh_string_free(tmp); return NULL; } ssh_string_free(tmp); switch(sign->type) { case SSH_KEYTYPE_DSS: #ifdef HAVE_LIBGCRYPT sexp = gcry_sexp_find_token(sign->dsa_sign, "r", 0); if (sexp == NULL) { ssh_buffer_free(tmpbuf); return NULL; } r = gcry_sexp_nth_data(sexp, 1, &size); if (*r == 0) { /* libgcrypt put 0 when first bit is set */ size--; r++; } memcpy(buffer, r + size - 20, 20); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(sign->dsa_sign, "s", 0); if (sexp == NULL) { ssh_buffer_free(tmpbuf); return NULL; } s = gcry_sexp_nth_data(sexp,1,&size); if (*s == 0) { size--; s++; } memcpy(buffer+ 20, s + size - 20, 20); gcry_sexp_release(sexp); #elif defined HAVE_LIBCRYPTO r = make_bignum_string(sign->dsa_sign->r); if (r == NULL) { ssh_buffer_free(tmpbuf); return NULL; } s = make_bignum_string(sign->dsa_sign->s); if (s == NULL) { ssh_buffer_free(tmpbuf); ssh_string_free(r); return NULL; } memcpy(buffer, (char *)ssh_string_data(r) + ssh_string_len(r) - 20, 20); memcpy(buffer + 20, (char *)ssh_string_data(s) + ssh_string_len(s) - 20, 20); ssh_string_free(r); ssh_string_free(s); #endif /* HAVE_LIBCRYPTO */ rs = ssh_string_new(40); if (rs == NULL) { ssh_buffer_free(tmpbuf); return NULL; } ssh_string_fill(rs, buffer, 40); rc = buffer_add_ssh_string(tmpbuf, rs); ssh_string_free(rs); if (rc < 0) { ssh_buffer_free(tmpbuf); return NULL; } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: #ifdef HAVE_LIBGCRYPT sexp = gcry_sexp_find_token(sign->rsa_sign, "s", 0); if (sexp == NULL) { ssh_buffer_free(tmpbuf); return NULL; } s = gcry_sexp_nth_data(sexp,1,&size); if (*s == 0) { size--; s++; } rs = ssh_string_new(size); if (rs == NULL) { ssh_buffer_free(tmpbuf); return NULL; } ssh_string_fill(rs, (char *) s, size); rc = buffer_add_ssh_string(tmpbuf, rs); gcry_sexp_release(sexp); ssh_string_free(rs); if (rc < 0) { ssh_buffer_free(tmpbuf); return NULL; } #elif defined HAVE_LIBCRYPTO if (buffer_add_ssh_string(tmpbuf,sign->rsa_sign) < 0) { ssh_buffer_free(tmpbuf); return NULL; } #endif break; } str = ssh_string_new(buffer_get_rest_len(tmpbuf)); if (str == NULL) { ssh_buffer_free(tmpbuf); return NULL; } ssh_string_fill(str, buffer_get_rest(tmpbuf), buffer_get_rest_len(tmpbuf)); ssh_buffer_free(tmpbuf); return str; }
int ssh_userauth1_password(ssh_session session, const char *username, const char *password) { ssh_string pwd = NULL; int rc; enter_function(); rc = send_username(session, username); if (rc != SSH_AUTH_DENIED) { leave_function(); return rc; } /* we trick a bit here. A known flaw in SSH1 protocol is that it's * easy to guess password sizes. * not that sure ... */ /* XXX fix me here ! */ /* cisco IOS doesn't like when a password is followed by zeroes and random pad. */ if(1 || strlen(password) >= 128) { /* not risky to disclose the size of such a big password .. */ pwd = ssh_string_from_char(password); if (pwd == NULL) { leave_function(); return SSH_AUTH_ERROR; } } else { /* fill the password string from random things. the strcpy * ensure there is at least a nul byte after the password. * most implementation won't see the garbage at end. * why garbage ? because nul bytes will be compressed by * gzip and disclose password len. */ pwd = ssh_string_new(128); if (pwd == NULL) { leave_function(); return SSH_AUTH_ERROR; } ssh_get_random( pwd->string, 128, 0); strcpy((char *) pwd->string, password); } if (buffer_add_u8(session->out_buffer, SSH_CMSG_AUTH_PASSWORD) < 0) { ssh_string_burn(pwd); ssh_string_free(pwd); leave_function(); return SSH_AUTH_ERROR; } if (buffer_add_ssh_string(session->out_buffer, pwd) < 0) { ssh_string_burn(pwd); ssh_string_free(pwd); leave_function(); return SSH_AUTH_ERROR; } ssh_string_burn(pwd); ssh_string_free(pwd); session->auth_state=SSH_AUTH_STATE_NONE; if (packet_send(session) == SSH_ERROR) { leave_function(); return SSH_AUTH_ERROR; } rc = wait_auth1_status(session); leave_function(); return rc; }
/** * @brief Check the public key in the known host line matches the public key of * the currently connected server. * * @param[in] session The SSH session to use. * * @param[in] tokens A list of tokens in the known_hosts line. * * @returns 1 if the key matches, 0 if the key doesn't match and -1 * on error. */ static int check_public_key(ssh_session session, char **tokens) { ssh_string pubkey = session->current_crypto->server_pubkey; ssh_buffer pubkey_buffer; char *pubkey_64; /* ok we found some public key in known hosts file. now un-base64it */ if (alldigits(tokens[1])) { /* openssh rsa1 format */ bignum tmpbn; ssh_string tmpstring; unsigned int len; int i; pubkey_buffer = ssh_buffer_new(); if (pubkey_buffer == NULL) { return -1; } tmpstring = ssh_string_from_char("ssh-rsa1"); if (tmpstring == NULL) { ssh_buffer_free(pubkey_buffer); return -1; } if (buffer_add_ssh_string(pubkey_buffer, tmpstring) < 0) { ssh_buffer_free(pubkey_buffer); ssh_string_free(tmpstring); return -1; } ssh_string_free(tmpstring); for (i = 2; i < 4; i++) { /* e, then n */ tmpbn = NULL; bignum_dec2bn(tokens[i], &tmpbn); if (tmpbn == NULL) { ssh_buffer_free(pubkey_buffer); return -1; } /* for some reason, make_bignum_string does not work because of the padding which it does --kv */ /* tmpstring = make_bignum_string(tmpbn); */ /* do it manually instead */ len = bignum_num_bytes(tmpbn); tmpstring = malloc(4 + len); if (tmpstring == NULL) { ssh_buffer_free(pubkey_buffer); bignum_free(tmpbn); return -1; } /* TODO: fix the hardcoding */ tmpstring->size = htonl(len); #ifdef HAVE_LIBGCRYPT bignum_bn2bin(tmpbn, len, tmpstring->string); #elif defined HAVE_LIBCRYPTO bignum_bn2bin(tmpbn, tmpstring->string); #endif bignum_free(tmpbn); if (buffer_add_ssh_string(pubkey_buffer, tmpstring) < 0) { ssh_buffer_free(pubkey_buffer); ssh_string_free(tmpstring); bignum_free(tmpbn); return -1; } ssh_string_free(tmpstring); } } else { /* ssh-dss or ssh-rsa */ pubkey_64 = tokens[2]; pubkey_buffer = base64_to_bin(pubkey_64); } if (pubkey_buffer == NULL) { ssh_set_error(session, SSH_FATAL, "Verifying that server is a known host: base64 error"); return -1; } if (buffer_get_rest_len(pubkey_buffer) != ssh_string_len(pubkey)) { ssh_buffer_free(pubkey_buffer); return 0; } /* now test that they are identical */ if (memcmp(buffer_get_rest(pubkey_buffer), pubkey->string, buffer_get_rest_len(pubkey_buffer)) != 0) { ssh_buffer_free(pubkey_buffer); return 0; } ssh_buffer_free(pubkey_buffer); return 1; }
/** * @brief Disconnect from a session (client or server). * The session can then be reused to open a new session. * * @param[in] session The SSH session to use. */ void ssh_disconnect(ssh_session session) { ssh_string str = NULL; struct ssh_iterator *it; if (session == NULL) { return; } if (session->socket != NULL && ssh_socket_is_open(session->socket)) { if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) { goto error; } if (buffer_add_u32(session->out_buffer, htonl(SSH2_DISCONNECT_BY_APPLICATION)) < 0) { goto error; } str = ssh_string_from_char("Bye Bye"); if (str == NULL) { goto error; } if (buffer_add_ssh_string(session->out_buffer,str) < 0) { ssh_string_free(str); goto error; } ssh_string_free(str); packet_send(session); ssh_socket_close(session->socket); } error: session->alive = 0; if (session->socket != NULL){ ssh_socket_reset(session->socket); } session->opts.fd = SSH_INVALID_SOCKET; session->session_state=SSH_SESSION_STATE_DISCONNECTED; while ((it=ssh_list_get_iterator(session->channels)) != NULL) { ssh_channel_do_free(ssh_iterator_value(ssh_channel,it)); ssh_list_remove(session->channels, it); } if(session->current_crypto){ crypto_free(session->current_crypto); session->current_crypto=NULL; } if (session->in_buffer) { ssh_buffer_reinit(session->in_buffer); } if (session->out_buffer) { ssh_buffer_reinit(session->out_buffer); } if (session->in_hashbuf) { ssh_buffer_reinit(session->in_hashbuf); } if (session->out_hashbuf) { ssh_buffer_reinit(session->out_hashbuf); } session->auth_methods = 0; SAFE_FREE(session->serverbanner); SAFE_FREE(session->clientbanner); if(session->ssh_message_list){ ssh_message msg; while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list)) != NULL){ ssh_message_free(msg); } ssh_list_free(session->ssh_message_list); session->ssh_message_list=NULL; } if (session->packet_callbacks){ ssh_list_free(session->packet_callbacks); session->packet_callbacks=NULL; } }
/** @internal * replies to an SSH_AUTH packet with a default (denied) response. */ int ssh_auth_reply_default(ssh_session session,int partial) { char methods_c[128] = {0}; ssh_string methods = NULL; int rc = SSH_ERROR; if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_FAILURE) < 0) { return rc; } if (session->auth_methods == 0) { session->auth_methods = SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD; } if (session->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) { strncat(methods_c, "publickey,", sizeof(methods_c) - strlen(methods_c) - 1); } if (session->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC){ strncat(methods_c,"gssapi-with-mic,", sizeof(methods_c) - strlen(methods_c) - 1); } if (session->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { strncat(methods_c, "keyboard-interactive,", sizeof(methods_c) - strlen(methods_c) - 1); } if (session->auth_methods & SSH_AUTH_METHOD_PASSWORD) { strncat(methods_c, "password,", sizeof(methods_c) - strlen(methods_c) - 1); } if (session->auth_methods & SSH_AUTH_METHOD_HOSTBASED) { strncat(methods_c, "hostbased,", sizeof(methods_c) - strlen(methods_c) - 1); } if (methods_c[0] == '\0' || methods_c[strlen(methods_c)-1] != ',') { return SSH_ERROR; } /* Strip the comma. */ methods_c[strlen(methods_c) - 1] = '\0'; // strip the comma. We are sure there is at SSH_LOG(SSH_LOG_PACKET, "Sending a auth failure. methods that can continue: %s", methods_c); methods = ssh_string_from_char(methods_c); if (methods == NULL) { goto error; } if (buffer_add_ssh_string(session->out_buffer, methods) < 0) { goto error; } if (partial) { if (buffer_add_u8(session->out_buffer, 1) < 0) { goto error; } } else { if (buffer_add_u8(session->out_buffer, 0) < 0) { goto error; } } rc = packet_send(session); error: ssh_string_free(methods); return rc; }
int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col, int row) { ssh_session session; ssh_string str = NULL; if (channel == NULL) { return SSH_ERROR; } session = channel->session; if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){ ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state"); return SSH_ERROR; } str = ssh_string_from_char(terminal); if (str == NULL) { ssh_set_error_oom(session); return -1; } if (buffer_add_u8(session->out_buffer, SSH_CMSG_REQUEST_PTY) < 0 || buffer_add_ssh_string(session->out_buffer, str) < 0) { ssh_string_free(str); return -1; } ssh_string_free(str); if (buffer_add_u32(session->out_buffer, ntohl(row)) < 0 || buffer_add_u32(session->out_buffer, ntohl(col)) < 0 || buffer_add_u32(session->out_buffer, 0) < 0 || /* x */ buffer_add_u32(session->out_buffer, 0) < 0 || /* y */ buffer_add_u8(session->out_buffer, 0) < 0) { /* tty things */ return -1; } ssh_log(session, SSH_LOG_FUNCTIONS, "Opening a ssh1 pty"); channel->request_state = SSH_CHANNEL_REQ_STATE_PENDING; if (packet_send(session) == SSH_ERROR) { return -1; } while (channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING) { ssh_handle_packets(session, SSH_TIMEOUT_INFINITE); } switch(channel->request_state){ case SSH_CHANNEL_REQ_STATE_ERROR: case SSH_CHANNEL_REQ_STATE_PENDING: case SSH_CHANNEL_REQ_STATE_NONE: channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; return SSH_ERROR; case SSH_CHANNEL_REQ_STATE_ACCEPTED: channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; ssh_log(session, SSH_LOG_RARE, "PTY: Success"); return SSH_OK; case SSH_CHANNEL_REQ_STATE_DENIED: channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; ssh_set_error(session, SSH_REQUEST_DENIED, "Server denied PTY allocation"); ssh_log(session, SSH_LOG_RARE, "PTY: denied\n"); return SSH_ERROR; } // Not reached return SSH_ERROR; }
int ssh_message_auth_interactive_request(ssh_message msg, const char *name, const char *instruction, unsigned int num_prompts, const char **prompts, char *echo) { int r; unsigned int i = 0; ssh_string tmp = NULL; if(name == NULL || instruction == NULL) { return SSH_ERROR; } if(num_prompts > 0 && (prompts == NULL || echo == NULL)) { return SSH_ERROR; } if (buffer_add_u8(msg->session->out_buffer, SSH2_MSG_USERAUTH_INFO_REQUEST) < 0) { return SSH_ERROR; } /* name */ tmp = ssh_string_from_char(name); if (tmp == NULL) { return SSH_ERROR; } r = buffer_add_ssh_string(msg->session->out_buffer, tmp); ssh_string_free(tmp); if (r < 0) { return SSH_ERROR; } /* instruction */ tmp = ssh_string_from_char(instruction); if (tmp == NULL) { return SSH_ERROR; } r = buffer_add_ssh_string(msg->session->out_buffer, tmp); ssh_string_free(tmp); if (r < 0) { return SSH_ERROR; } /* language tag */ tmp = ssh_string_from_char(""); if (tmp == NULL) { return SSH_ERROR; } r = buffer_add_ssh_string(msg->session->out_buffer, tmp); ssh_string_free(tmp); if (r < 0) { return SSH_ERROR; } /* num prompts */ if (buffer_add_u32(msg->session->out_buffer, ntohl(num_prompts)) < 0) { return SSH_ERROR; } for(i = 0; i < num_prompts; i++) { /* prompt[i] */ tmp = ssh_string_from_char(prompts[i]); if (tmp == NULL) { return SSH_ERROR; } r = buffer_add_ssh_string(msg->session->out_buffer, tmp); ssh_string_free(tmp); if (r < 0) { return SSH_ERROR; } /* echo[i] */ if (buffer_add_u8(msg->session->out_buffer, echo[i]) < 0) { return SSH_ERROR; } } r = packet_send(msg->session); /* fill in the kbdint structure */ if (msg->session->kbdint == NULL) { SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Got a " "keyboard-interactive response but it " "seems we didn't send the request."); msg->session->kbdint = ssh_kbdint_new(); if (msg->session->kbdint == NULL) { ssh_set_error_oom(msg->session); return SSH_ERROR; } } else { ssh_kbdint_clean(msg->session->kbdint); } msg->session->kbdint->name = strdup(name); if(msg->session->kbdint->name == NULL) { ssh_set_error_oom(msg->session); ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_PACKET_USED; } msg->session->kbdint->instruction = strdup(instruction); if(msg->session->kbdint->instruction == NULL) { ssh_set_error_oom(msg->session); ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_PACKET_USED; } msg->session->kbdint->nprompts = num_prompts; if(num_prompts > 0) { msg->session->kbdint->prompts = malloc(num_prompts * sizeof(char *)); if (msg->session->kbdint->prompts == NULL) { msg->session->kbdint->nprompts = 0; ssh_set_error_oom(msg->session); ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_ERROR; } msg->session->kbdint->echo = malloc(num_prompts * sizeof(unsigned char)); if (msg->session->kbdint->echo == NULL) { ssh_set_error_oom(msg->session); ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_ERROR; } for (i = 0; i < num_prompts; i++) { msg->session->kbdint->echo[i] = echo[i]; msg->session->kbdint->prompts[i] = strdup(prompts[i]); if (msg->session->kbdint->prompts[i] == NULL) { ssh_set_error_oom(msg->session); msg->session->kbdint->nprompts = i; ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_PACKET_USED; } } } else { msg->session->kbdint->prompts = NULL; msg->session->kbdint->echo = NULL; } return r; }