/** * @brief Get the issue banner from the server. * * This is the banner showing a disclaimer to users who log in, * typically their right or the fact that they will be monitored. * * @param[in] session The SSH session to use. * * @return A newly allocated string with the banner, NULL on error. */ char *ssh_get_issue_banner(ssh_session session) { if (session == NULL || session->banner == NULL) { return NULL; } return ssh_string_to_char(session->banner); }
/* caller has to free commment */ ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session, char **comment) { struct ssh_key_struct *key; struct ssh_string_struct *blob = NULL; struct ssh_string_struct *tmp = NULL; int rc; 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) { ssh_string_free(blob); return NULL; } if (comment) { *comment = ssh_string_to_char(tmp); } else { ssh_string_free(blob); ssh_string_free(tmp); return NULL; } ssh_string_free(tmp); /* get key from blob */ rc = ssh_pki_import_pubkey_blob(blob, &key); ssh_string_free(blob); if (rc == SSH_ERROR) { return NULL; } break; default: return NULL; } return key; }
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 = ssh_buffer_new(); if (tmpbuf == NULL) { return NULL; } if (buffer_add_data(tmpbuf, ssh_string_data(pubkey_s), ssh_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 = ssh_string_to_char(type_s); ssh_string_free(type_s); if (type_c == NULL) { goto error; } type = ssh_type_from_name(type_c); SAFE_FREE(type_c); switch (type) { case SSH_KEYTYPE_DSS: return publickey_make_dss(session, tmpbuf); case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_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: ssh_buffer_free(tmpbuf); return NULL; }
/* 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; } ZERO_STRUCTP(sign); tmpbuf = ssh_buffer_new(); if (tmpbuf == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); signature_free(sign); return NULL; } if (buffer_add_data(tmpbuf, ssh_string_data(signature), ssh_string_len(signature)) < 0) { signature_free(sign); ssh_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); ssh_buffer_free(tmpbuf); return NULL; } type_c = ssh_string_to_char(type_s); ssh_string_free(type_s); if (type_c == NULL) { signature_free(sign); ssh_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); ssh_buffer_free(tmpbuf); return NULL; } switch(needed_type) { case SSH_KEYTYPE_DSS: rs = buffer_get_ssh_string(tmpbuf); ssh_buffer_free(tmpbuf); /* 40 is the dual signature blob len. */ if (rs == NULL || ssh_string_len(rs) != 40) { ssh_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 ,ssh_string_data(rs), 20,(unsigned char *)ssh_string_data(rs) + 20)) { ssh_string_free(rs); signature_free(sign); return NULL; } #elif defined HAVE_LIBCRYPTO r = ssh_string_new(20); s = ssh_string_new(20); if (r == NULL || s == NULL) { ssh_string_free(r); ssh_string_free(s); ssh_string_free(rs); signature_free(sign); return NULL; } ssh_string_fill(r, ssh_string_data(rs), 20); ssh_string_fill(s, (char *)ssh_string_data(rs) + 20, 20); sig = DSA_SIG_new(); if (sig == NULL) { ssh_string_free(r); ssh_string_free(s); ssh_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); ssh_string_free(r); ssh_string_free(s); if (sig->r == NULL || sig->s == NULL) { ssh_string_free(rs); DSA_SIG_free(sig); signature_free(sign); return NULL; } #endif #ifdef DEBUG_CRYPTO ssh_print_hexa("r", ssh_string_data(rs), 20); ssh_print_hexa("s", (const unsigned char *)ssh_string_data(rs) + 20, 20); #endif ssh_string_free(rs); sign->type = SSH_KEYTYPE_DSS; sign->dsa_sign = sig; return sign; case SSH_KEYTYPE_RSA: e = buffer_get_ssh_string(tmpbuf); ssh_buffer_free(tmpbuf); if (e == NULL) { signature_free(sign); return NULL; } len = ssh_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) { ssh_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 = SSH_KEYTYPE_RSA; #ifdef HAVE_LIBGCRYPT if (gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))", ssh_string_len(e), ssh_string_data(e))) { signature_free(sign); ssh_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", ssh_string_data(e), len); #endif #ifdef HAVE_LIBGCRYPT ssh_string_free(e); #endif return sign; default: return NULL; } return NULL; }
/** * @internal * * @brief This function parses the last end of a channel request packet. * * This is normally converted to a SSH message and placed in the queue. * * @param[in] session The SSH session. * * @param[in] channel The channel the request is made on. * * @param[in] packet The rest of the packet to be parsed. * * @param[in] request The type of request. * * @param[in] want_reply The want_reply field from the request. * * @returns SSH_OK on success, SSH_ERROR if an error occured. */ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel, ssh_buffer packet, const char *request, uint8_t want_reply) { ssh_message msg = NULL; enter_function(); msg = ssh_message_new(session); if (msg == NULL) { ssh_set_error_oom(session); goto error; } ssh_log(session, SSH_LOG_PACKET, "Received a %s channel_request for channel (%d:%d) (want_reply=%hhd)", request, channel->local_channel, channel->remote_channel, want_reply); msg->type = SSH_REQUEST_CHANNEL; msg->channel_request.channel = channel; msg->channel_request.want_reply = want_reply; if (strcmp(request, "pty-req") == 0) { ssh_string term = NULL; char *term_c = NULL; term = buffer_get_ssh_string(packet); if (term == NULL) { ssh_set_error_oom(session); goto error; } term_c = ssh_string_to_char(term); if (term_c == NULL) { ssh_set_error_oom(session); ssh_string_free(term); goto error; } ssh_string_free(term); msg->channel_request.type = SSH_CHANNEL_REQUEST_PTY; msg->channel_request.TERM = term_c; buffer_get_u32(packet, &msg->channel_request.width); buffer_get_u32(packet, &msg->channel_request.height); buffer_get_u32(packet, &msg->channel_request.pxwidth); buffer_get_u32(packet, &msg->channel_request.pxheight); msg->channel_request.width = ntohl(msg->channel_request.width); msg->channel_request.height = ntohl(msg->channel_request.height); msg->channel_request.pxwidth = ntohl(msg->channel_request.pxwidth); msg->channel_request.pxheight = ntohl(msg->channel_request.pxheight); msg->channel_request.modes = buffer_get_ssh_string(packet); if (msg->channel_request.modes == NULL) { SAFE_FREE(term_c); goto error; } goto end; } if (strcmp(request, "window-change") == 0) { msg->channel_request.type = SSH_CHANNEL_REQUEST_WINDOW_CHANGE; buffer_get_u32(packet, &msg->channel_request.width); buffer_get_u32(packet, &msg->channel_request.height); buffer_get_u32(packet, &msg->channel_request.pxwidth); buffer_get_u32(packet, &msg->channel_request.pxheight); msg->channel_request.width = ntohl(msg->channel_request.width); msg->channel_request.height = ntohl(msg->channel_request.height); msg->channel_request.pxwidth = ntohl(msg->channel_request.pxwidth); msg->channel_request.pxheight = ntohl(msg->channel_request.pxheight); goto end; } if (strcmp(request, "subsystem") == 0) { ssh_string subsys = NULL; char *subsys_c = NULL; subsys = buffer_get_ssh_string(packet); if (subsys == NULL) { ssh_set_error_oom(session); goto error; } subsys_c = ssh_string_to_char(subsys); if (subsys_c == NULL) { ssh_set_error_oom(session); ssh_string_free(subsys); goto error; } ssh_string_free(subsys); msg->channel_request.type = SSH_CHANNEL_REQUEST_SUBSYSTEM; msg->channel_request.subsystem = subsys_c; goto end; } if (strcmp(request, "shell") == 0) { msg->channel_request.type = SSH_CHANNEL_REQUEST_SHELL; goto end; } if (strcmp(request, "exec") == 0) { ssh_string cmd = NULL; cmd = buffer_get_ssh_string(packet); if (cmd == NULL) { ssh_set_error_oom(session); goto error; } msg->channel_request.type = SSH_CHANNEL_REQUEST_EXEC; msg->channel_request.command = ssh_string_to_char(cmd); ssh_string_free(cmd); if (msg->channel_request.command == NULL) { goto error; } goto end; } if (strcmp(request, "env") == 0) { ssh_string name = NULL; ssh_string value = NULL; name = buffer_get_ssh_string(packet); if (name == NULL) { ssh_set_error_oom(session); goto error; } value = buffer_get_ssh_string(packet); if (value == NULL) { ssh_set_error_oom(session); ssh_string_free(name); goto error; } msg->channel_request.type = SSH_CHANNEL_REQUEST_ENV; msg->channel_request.var_name = ssh_string_to_char(name); msg->channel_request.var_value = ssh_string_to_char(value); if (msg->channel_request.var_name == NULL || msg->channel_request.var_value == NULL) { ssh_string_free(name); ssh_string_free(value); goto error; } ssh_string_free(name); ssh_string_free(value); goto end; } if (strcmp(request, "x11-req") == 0) { ssh_string auth_protocol = NULL; ssh_string auth_cookie = NULL; buffer_get_u8(packet, &msg->channel_request.x11_single_connection); auth_protocol = buffer_get_ssh_string(packet); if (auth_protocol == NULL) { ssh_set_error_oom(session); goto error; } auth_cookie = buffer_get_ssh_string(packet); if (auth_cookie == NULL) { ssh_set_error_oom(session); ssh_string_free(auth_protocol); goto error; } msg->channel_request.type = SSH_CHANNEL_REQUEST_X11; msg->channel_request.x11_auth_protocol = ssh_string_to_char(auth_protocol); msg->channel_request.x11_auth_cookie = ssh_string_to_char(auth_cookie); if (msg->channel_request.x11_auth_protocol == NULL || msg->channel_request.x11_auth_cookie == NULL) { ssh_string_free(auth_protocol); ssh_string_free(auth_cookie); goto error; } ssh_string_free(auth_protocol); ssh_string_free(auth_cookie); buffer_get_u32(packet, &msg->channel_request.x11_screen_number); goto end; } msg->channel_request.type = SSH_CHANNEL_UNKNOWN; end: ssh_message_queue(session,msg); leave_function(); return SSH_OK; error: ssh_message_free(msg); leave_function(); return SSH_ERROR; }
const char *sftp_client_message_get_data(sftp_client_message msg){ if (msg->str_data == NULL) msg->str_data = ssh_string_to_char(msg->data); return msg->str_data; }
char *string_to_char(ssh_string str){ return ssh_string_to_char(str); }