/* {{{ libssh2_publickey_response_success * Generic helper routine to wait for success response and nothing else */ static int libssh2_publickey_response_success(LIBSSH2_PUBLICKEY *pkey) { LIBSSH2_SESSION *session = pkey->channel->session; unsigned char *data, *s; unsigned long data_len, response; while (1) { if (libssh2_publickey_packet_receive(pkey, &data, &data_len)) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for response from publickey subsystem", 0); return -1; } s = data; if ((response = libssh2_publickey_response_id(&s, data_len)) < 0) { libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Invalid publickey subsystem response code", 0); LIBSSH2_FREE(session, data); return -1; } switch (response) { case LIBSSH2_PUBLICKEY_RESPONSE_STATUS: /* Error, or processing complete */ { unsigned long status, descr_len, lang_len; unsigned char *descr, *lang; status = libssh2_ntohu32(s); s += 4; descr_len = libssh2_ntohu32(s); s += 4; descr = s; s += descr_len; lang_len = libssh2_ntohu32(s); s += 4; lang = s; s += lang_len; if (s > data + data_len) { libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Malformed publickey subsystem packet", 0); LIBSSH2_FREE(session, data); return -1; } if (status == LIBSSH2_PUBLICKEY_SUCCESS) { LIBSSH2_FREE(session, data); return 0; } libssh2_publickey_status_error(pkey, session, status, descr, descr_len); LIBSSH2_FREE(session, data); return -1; } default: /* Unknown/Unexpected */ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Unexpected publickey subsystem response, ignoring", 0); LIBSSH2_FREE(session, data); data = NULL; } } /* never reached, but include `return` to silence compiler warnings */ return -1; }
/* * _libssh2_packet_burn * * Loops _libssh2_transport_read() until any packet is available and promptly * discards it. * Used during KEX exchange to discard badly guessed KEX_INIT packets */ int _libssh2_packet_burn(LIBSSH2_SESSION * session, libssh2_nonblocking_states * state) { unsigned char *data; size_t data_len; unsigned char i, all_packets[255]; int ret; if (*state == libssh2_NB_state_idle) { for(i = 1; i < 255; i++) { all_packets[i - 1] = i; } all_packets[254] = 0; if (_libssh2_packet_askv(session, all_packets, &data, &data_len, 0, NULL, 0) == 0) { i = data[0]; /* A packet was available in the packet brigade, burn it */ LIBSSH2_FREE(session, data); return i; } _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Blocking until packet becomes available to burn"); *state = libssh2_NB_state_created; } while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { ret = _libssh2_transport_read(session); if (ret == LIBSSH2_ERROR_EAGAIN) { return ret; } else if (ret < 0) { *state = libssh2_NB_state_idle; return ret; } else if (ret == 0) { /* FIXME: this might busyloop */ continue; } /* Be lazy, let packet_ask pull it out of the brigade */ if (0 == _libssh2_packet_ask(session, (unsigned char)ret, &data, &data_len, 0, NULL, 0)) { /* Smoke 'em if you got 'em */ LIBSSH2_FREE(session, data); *state = libssh2_NB_state_idle; return ret; } } /* Only reached if the socket died */ return LIBSSH2_ERROR_SOCKET_DISCONNECT; }
/* {{{ libssh2_packet_burn * Loops libssh2_packet_read() until any packet is available and promptly * discards it * Used during KEX exchange to discard badly guessed KEX_INIT packets */ int libssh2_packet_burn(LIBSSH2_SESSION * session, libssh2_nonblocking_states * state) { unsigned char *data; unsigned long data_len; unsigned char all_packets[255]; int i; int ret; if (*state == libssh2_NB_state_idle) { for(i = 1; i < 256; i++) { all_packets[i - 1] = i; } if (libssh2_packet_askv_ex (session, all_packets, &data, &data_len, 0, NULL, 0, 0) == 0) { i = data[0]; /* A packet was available in the packet brigade, burn it */ LIBSSH2_FREE(session, data); return i; } _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Blocking until packet becomes available to burn"); *state = libssh2_NB_state_created; } while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { if ((ret = libssh2_packet_read(session)) == PACKET_EAGAIN) { return PACKET_EAGAIN; } else if (ret < 0) { *state = libssh2_NB_state_idle; return ret; } else if (ret == 0) { /* FIXME: this might busyloop */ continue; } /* Be lazy, let packet_ask pull it out of the brigade */ if (0 == libssh2_packet_ask_ex(session, ret, &data, &data_len, 0, NULL, 0, 0)) { /* Smoke 'em if you got 'em */ LIBSSH2_FREE(session, data); *state = libssh2_NB_state_idle; return ret; } } /* Only reached if the socket died */ return -1; }
static void free_host(LIBSSH2_SESSION *session, struct known_host *entry) { if(entry) { if(entry->key) LIBSSH2_FREE(session, entry->key); if(entry->salt) LIBSSH2_FREE(session, entry->salt); if(entry->name) LIBSSH2_FREE(session, entry->name); LIBSSH2_FREE(session, entry); } }
/* {{{ proto libssh2_userauth_list * List authentication methods * Will yield successful login if "none" happens to be allowable for this user * Not a common configuration for any SSH server though * username should be NULL, or a null terminated string */ LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, const char *username, unsigned int username_len) { unsigned char reply_codes[3] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 }; unsigned long data_len = username_len + 31; /* packet_type(1) + username_len(4) + service_len(4) + service(14)"ssh-connection" + method_len(4) + method(4)"none" */ unsigned long methods_len; unsigned char *data, *s; s = data = LIBSSH2_ALLOC(session, data_len); if (!data) { libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for userauth_list", 0); return NULL; } *(s++) = SSH_MSG_USERAUTH_REQUEST; libssh2_htonu32(s, username_len); s += 4; if (username) { memcpy(s, username, username_len); s += username_len; } libssh2_htonu32(s, 14); s += 4; memcpy(s, "ssh-connection", 14); s += 14; libssh2_htonu32(s, 4); s += 4; memcpy(s, "none", 4); s += 4; if (libssh2_packet_write(session, data, data_len)) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-none request", 0); LIBSSH2_FREE(session, data); return NULL; } LIBSSH2_FREE(session, data); if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) { return NULL; } if (data[0] == SSH_MSG_USERAUTH_SUCCESS) { /* Wow, who'dve thought... */ LIBSSH2_FREE(session, data); session->state |= LIBSSH2_STATE_AUTHENTICATED; return NULL; } methods_len = libssh2_ntohu32(data + 1); memcpy(data, data + 5, methods_len); data[methods_len] = '\0'; #ifdef LIBSSH2_DEBUG_USERAUTH _libssh2_debug(session, LIBSSH2_DBG_AUTH, "Permitted auth methods: %s", data); #endif return (char *)data; }
static void agent_free_identities(LIBSSH2_AGENT *agent) { struct agent_publickey *node; struct agent_publickey *next; for (node = _libssh2_list_first(&agent->head); node; node = next) { next = _libssh2_list_next(&node->node); LIBSSH2_FREE(agent->session, node->external.blob); LIBSSH2_FREE(agent->session, node->external.comment); LIBSSH2_FREE(agent->session, node); } _libssh2_list_init(&agent->head); }
/* {{{ libssh2_publickey_list_free * Free a previously fetched list of public keys */ LIBSSH2_API void libssh2_publickey_list_free(LIBSSH2_PUBLICKEY *pkey, libssh2_publickey_list *pkey_list) { LIBSSH2_SESSION *session = pkey->channel->session; libssh2_publickey_list *p = pkey_list; while (p->packet) { if (p->attrs) { LIBSSH2_FREE(session, p->attrs); } LIBSSH2_FREE(session, p->packet); p++; } LIBSSH2_FREE(session, pkey_list); }
static void libssh2_comp_method_zlib_free(voidpf opaque, voidpf address) { LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque; LIBSSH2_FREE(session, address); }
/* {{{ libssh2_publickey_shutdown * Shutdown the publickey subsystem */ LIBSSH2_API void libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey) { LIBSSH2_SESSION *session = pkey->channel->session; libssh2_channel_free(pkey->channel); LIBSSH2_FREE(session, pkey); }
/* {{{ libssh2_publickey_packet_receive * Read a packet from the subsystem */ static int libssh2_publickey_packet_receive(LIBSSH2_PUBLICKEY *pkey, unsigned char **data, unsigned long *data_len) { LIBSSH2_CHANNEL *channel = pkey->channel; LIBSSH2_SESSION *session = channel->session; unsigned char buffer[4]; unsigned long packet_len; unsigned char *packet; if (libssh2_channel_read(channel, buffer, 4) != 4) { libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Invalid response from publickey subsystem", 0); return -1; } packet_len = libssh2_ntohu32(buffer); packet = LIBSSH2_ALLOC(session, packet_len); if (!packet) { libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate publickey response buffer", 0); return -1; } if (libssh2_channel_read(channel, packet, packet_len) != packet_len) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for publickey subsystem response packet", 0); LIBSSH2_FREE(session, packet); return -1; } *data = packet; *data_len = packet_len; return 0; }
/* * hostkey_method_ssh_dss_signv * * Construct a signature from an array of vectors */ static int hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session, unsigned char **signature, size_t *signature_len, int veccount, const struct iovec datavec[], void **abstract) { libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract); unsigned char hash[SHA_DIGEST_LENGTH]; libssh2_sha1_ctx ctx; int i; *signature = LIBSSH2_CALLOC(session, 2 * SHA_DIGEST_LENGTH); if (!*signature) { return -1; } *signature_len = 2 * SHA_DIGEST_LENGTH; libssh2_sha1_init(&ctx); for(i = 0; i < veccount; i++) { libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len); } libssh2_sha1_final(ctx, hash); if (_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) { LIBSSH2_FREE(session, *signature); return -1; } return 0; }
/* {{{ libssh2_comp_method_zlib_init * All your bandwidth are belong to us (so save some) */ static int libssh2_comp_method_zlib_init(LIBSSH2_SESSION * session, int compress, void **abstract) { z_stream *strm; int status; strm = LIBSSH2_ALLOC(session, sizeof(z_stream)); if (!strm) { libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for zlib compression/decompression", 0); return -1; } memset(strm, 0, sizeof(z_stream)); strm->opaque = (voidpf) session; strm->zalloc = (alloc_func) libssh2_comp_method_zlib_alloc; strm->zfree = (free_func) libssh2_comp_method_zlib_free; if (compress) { /* deflate */ status = deflateInit(strm, Z_DEFAULT_COMPRESSION); } else { /* inflate */ status = inflateInit(strm); } if (status != Z_OK) { LIBSSH2_FREE(session, strm); return -1; } *abstract = strm; return 0; }
/* {{{ libssh2_banner_set * Set the local banner */ LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner) { int banner_len = banner ? strlen(banner) : 0; if (session->local.banner) { LIBSSH2_FREE(session, session->local.banner); session->local.banner = NULL; } if (!banner_len) { return 0; } session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3); if (!session->local.banner) { libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for local banner", 0); return -1; } memcpy(session->local.banner, banner, banner_len); session->local.banner[banner_len] = '\0'; _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Setting local Banner: %s", session->local.banner); session->local.banner[banner_len++] = '\r'; session->local.banner[banner_len++] = '\n'; session->local.banner[banner_len++] = '\0'; return 0; }
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, libssh2_rsa_ctx * rsactx, const unsigned char *hash, unsigned long hash_len, unsigned char **signature, unsigned long *signature_len) { int ret; unsigned char *sig; unsigned int sig_len; sig_len = RSA_size(rsactx); sig = LIBSSH2_ALLOC(session, sig_len); if (!sig) { return -1; } ret = RSA_sign(NID_sha1, hash, hash_len, sig, &sig_len, rsactx); if (!ret) { LIBSSH2_FREE(session, sig); return -1; } *signature = sig; *signature_len = sig_len; return 0; }
/* * _libssh2_packet_ask * * Scan the brigade for a matching packet type, optionally poll the socket for * a packet first */ int _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type, unsigned char **data, size_t *data_len, int match_ofs, const unsigned char *match_buf, size_t match_len) { LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets); _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Looking for packet of type: %d", (int) packet_type); while (packet) { if (packet->data[0] == packet_type && (packet->data_len >= (match_ofs + match_len)) && (!match_buf || (memcmp(packet->data + match_ofs, match_buf, match_len) == 0))) { *data = packet->data; *data_len = packet->data_len; /* unlink struct from session->packets */ _libssh2_list_remove(&packet->node); LIBSSH2_FREE(session, packet); return 0; } packet = _libssh2_list_next(&packet->node); } return -1; }
static libssh2pack_t decrypt(LIBSSH2_SESSION * session, unsigned char *source, unsigned char *dest, int len) { struct transportpacket *p = &session->packet; int blocksize = session->remote.crypt->blocksize; /* if we get called with a len that isn't an even number of blocksizes we risk losing those extra bytes */ assert((len % blocksize) == 0); while (len >= blocksize) { if (session->remote.crypt->crypt(session, source, &session->remote.crypt_abstract)) { libssh2_error(session, LIBSSH2_ERROR_DECRYPT, (char *) "Error decrypting packet", 0); LIBSSH2_FREE(session, p->payload); return PACKET_FAIL; } /* if the crypt() function would write to a given address it wouldn't have to memcpy() and we could avoid this memcpy() too */ memcpy(dest, source, blocksize); len -= blocksize; /* less bytes left */ dest += blocksize; /* advance write pointer */ source += blocksize; /* advance read pointer */ } return PACKET_NONE; /* all is fine */ }
/* {{{ libssh2_packet_ask * Scan the brigade for a matching packet type, optionally poll the socket for * a packet first */ int libssh2_packet_ask_ex(LIBSSH2_SESSION * session, unsigned char packet_type, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, int poll_socket) { LIBSSH2_PACKET *packet = session->packets.head; if (poll_socket) { /* * XXX CHECK *** * When "poll_socket" is "1" libhss2_packet_read() can return * PACKET_EAGAIN. I am not sure what should happen, but internally * there is only one location that might do so, libssh2_packet_askv_ex() */ libssh2pack_t rc = libssh2_packet_read(session); if ((rc < 0) && !packet) { return rc; } } _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Looking for packet of type: %d", (int) packet_type); while (packet) { if (packet->data[0] == packet_type && (packet->data_len >= (match_ofs + match_len)) && (!match_buf || (memcmp (packet-> data + match_ofs, match_buf, match_len) == 0))) { *data = packet->data; *data_len = packet->data_len; if (packet->prev) { packet->prev->next = packet->next; } else { session->packets.head = packet->next; } if (packet->next) { packet->next->prev = packet->prev; } else { session->packets.tail = packet->prev; } LIBSSH2_FREE(session, packet); return 0; } packet = packet->next; } return -1; }
/* {{{ libssh2_mac_method_common_dtor * Cleanup simple mac methods */ static int libssh2_mac_method_common_dtor(LIBSSH2_SESSION *session, void **abstract) { if (*abstract) { LIBSSH2_FREE(session, *abstract); } *abstract = NULL; return 0; }
/* * libssh2_agent_free() * * Free an ssh-agent handle. This function also frees the internal * collection of public keys. */ LIBSSH2_API void libssh2_agent_free(LIBSSH2_AGENT *agent) { /* Allow connection freeing when the socket has lost its connection */ if (agent->fd != INVALID_SOCKET) { libssh2_agent_disconnect(agent); } agent_free_identities(agent); LIBSSH2_FREE(agent->session, agent); }
/* {{{ libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange * Diffie-Hellman Group Exchange Key Exchange using SHA1 * Negotiates random(ish) group for secret derivation */ static int libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange(LIBSSH2_SESSION *session) { unsigned char request[13], *s, *data; unsigned long data_len, p_len, g_len, request_len; _libssh2_bn *p = _libssh2_bn_init (); _libssh2_bn *g = _libssh2_bn_init (); int ret; /* Ask for a P and G pair */ #ifdef LIBSSH2_DH_GEX_NEW request[0] = SSH_MSG_KEX_DH_GEX_REQUEST; libssh2_htonu32(request + 1, LIBSSH2_DH_GEX_MINGROUP); libssh2_htonu32(request + 5, LIBSSH2_DH_GEX_OPTGROUP); libssh2_htonu32(request + 9, LIBSSH2_DH_GEX_MAXGROUP); request_len = 13; #ifdef LIBSSH2_DEBUG_KEX _libssh2_debug(session, LIBSSH2_DBG_KEX, "Initiating Diffie-Hellman Group-Exchange (New Method)"); #endif #else request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD; libssh2_htonu32(request + 1, LIBSSH2_DH_GEX_OPTGROUP); request_len = 5; #ifdef LIBSSH2_DEBUG_KEX _libssh2_debug(session, LIBSSH2_DBG_KEX, "Initiating Diffie-Hellman Group-Exchange (Old Method)"); #endif #endif if (libssh2_packet_write(session, request, request_len)) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send Group Exchange Request", 0); ret = -1; goto dh_gex_clean_exit; } if (libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP, &data, &data_len)) { libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, "Timeout waiting for GEX_GROUP reply", 0); ret = -1; goto dh_gex_clean_exit; } s = data + 1; p_len = libssh2_ntohu32(s); s += 4; _libssh2_bn_from_bin(p, p_len, s); s += p_len; g_len = libssh2_ntohu32(s); s += 4; _libssh2_bn_from_bin(g, g_len, s); s += g_len; ret = libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(session, g, p, p_len, SSH_MSG_KEX_DH_GEX_INIT, SSH_MSG_KEX_DH_GEX_REPLY, data + 1, data_len - 1); LIBSSH2_FREE(session, data); dh_gex_clean_exit: _libssh2_bn_free(g); _libssh2_bn_free(p); return ret; }
/* {{{ libssh2_publickey_remove_ex * Remove an existing publickey so that authentication can no longer be performed using it */ LIBSSH2_API int libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, unsigned long name_len, const unsigned char *blob, unsigned long blob_len) { LIBSSH2_CHANNEL *channel = pkey->channel; LIBSSH2_SESSION *session = channel->session; unsigned char *s, *packet = NULL; unsigned long packet_len = 22 + name_len + blob_len; /* packet_len(4) + remove_len(4) + "remove"(6) + name_len(4) + {name} blob_len(4) + {blob} */ packet = LIBSSH2_ALLOC(session, packet_len); if (!packet) { libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for publickey \"remove\" packet", 0); return -1; } s = packet; libssh2_htonu32(s, packet_len - 4); s += 4; libssh2_htonu32(s, sizeof("remove") - 1); s += 4; memcpy(s, "remove", sizeof("remove") - 1); s += sizeof("remove") - 1; libssh2_htonu32(s, name_len); s += 4; memcpy(s, name, name_len); s += name_len; libssh2_htonu32(s, blob_len); s += 4; memcpy(s, blob, blob_len); s += blob_len; #ifdef LIBSSH2_DEBUG_PUBLICKEY _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Sending publickey \"remove\" packet: type=%s blob_len=%ld", name, blob_len); #endif if ((s - packet) != libssh2_channel_write(channel, packet, (s - packet))) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send publickey remove packet", 0); LIBSSH2_FREE(session, packet); return -1; } LIBSSH2_FREE(session, packet); packet = NULL; return libssh2_publickey_response_success(pkey); }
static int _libssh2_dtor(LIBSSH2_SESSION * session, void **abstract) { struct crypt_ctx **cctx = (struct crypt_ctx **) abstract; if (cctx && *cctx) { _libssh2_cipher_dtor(&(*cctx)->h); LIBSSH2_FREE(session, *cctx); *abstract = NULL; } return 0; }
static int gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, unsigned char **method, size_t *method_len, unsigned char **pubkeydata, size_t *pubkeydata_len, EVP_PKEY *pk) { DSA* dsa = NULL; unsigned char* key; unsigned char* method_buf = NULL; size_t key_len; _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Computing public key from DSA private key envelop"); dsa = EVP_PKEY_get1_DSA(pk); if (dsa == NULL) { /* Assume memory allocation error... what else could it be ? */ goto __alloc_error; } method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-dss. */ if (method_buf == NULL) { goto __alloc_error; } key = gen_publickey_from_dsa(session, dsa, &key_len); if (key == NULL) { goto __alloc_error; } DSA_free(dsa); memcpy(method_buf, "ssh-dss", 7); *method = method_buf; *method_len = 7; *pubkeydata = key; *pubkeydata_len = key_len; return 0; __alloc_error: if (dsa != NULL) { DSA_free(dsa); } if (method_buf != NULL) { LIBSSH2_FREE(session, method_buf); } _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for private key data"); return -1; }
/* * libssh2_knownhost_free * * Free an entire collection of known hosts. * */ LIBSSH2_API void libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts) { struct known_host *node; struct known_host *next; for(node = _libssh2_list_first(&hosts->head); node; node = next) { next = _libssh2_list_next(&node->node); free_host(hosts->session, node); } LIBSSH2_FREE(hosts->session, hosts); }
LIBSSH2_API void libssh2_release_string_cache(LIBSSH2_SESSION *session, libssh2_string_cache **cache) { libssh2_string_cache *p; if (session && cache) while ((p = *cache)) { *cache = p->next; LIBSSH2_FREE(session, (char *) p); } }
static libssh2pack_t send_existing(LIBSSH2_SESSION * session, unsigned char *data, unsigned long data_len, ssize_t * ret) { ssize_t rc; ssize_t length; struct transportpacket *p = &session->packet; if (!p->outbuf) { *ret = 0; return PACKET_NONE; } /* send as much as possible of the existing packet */ if ((data != p->odata) || (data_len != p->olen)) { /* When we are about to complete the sending of a packet, it is vital that the caller doesn't try to send a new/different packet since we don't add this one up until the previous one has been sent. To make the caller really notice his/hers flaw, we return error for this case */ return PACKET_BADUSE; } *ret = 1; /* set to make our parent return */ /* number of bytes left to send */ length = p->ototal_num - p->osent; rc = send(session->socket_fd, &p->outbuf[p->osent], length, LIBSSH2_SOCKET_SEND_FLAGS(session)); if (rc == length) { /* the remainder of the package was sent */ LIBSSH2_FREE(session, p->outbuf); p->outbuf = NULL; p->ototal_num = 0; } else if (rc < 0) { /* nothing was sent */ if (errno != EAGAIN) { /* send failure! */ return PACKET_FAIL; } return PACKET_EAGAIN; } debugdump(session, "libssh2_packet_write send()", &p->outbuf[p->osent], length); p->osent += length; /* we sent away this much data */ return PACKET_NONE; }
/* {{{ libssh2_packet_burn * Loops libssh2_packet_read() until any packet is available and promptly discards it * Used during KEX exchange to discard badly guessed KEX_INIT packets */ int libssh2_packet_burn(LIBSSH2_SESSION *session) { unsigned char *data; unsigned long data_len; char all_packets[255]; int i; for(i = 1; i < 256; i++) all_packets[i - 1] = i; if (libssh2_packet_askv_ex(session, all_packets, &data, &data_len, 0, NULL, 0, 0) == 0) { i = data[0]; /* A packet was available in the packet brigade, burn it */ LIBSSH2_FREE(session, data); return i; } #ifdef LIBSSH2_DEBUG_TRANSPORT _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Blocking until packet becomes available to burn"); #endif while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { int ret = libssh2_packet_read(session, 1); if (ret < 0) { return -1; } if (ret == 0) continue; /* Be lazy, let packet_ask pull it out of the brigade */ if (0 == libssh2_packet_ask_ex(session, ret, &data, &data_len, 0, NULL, 0, 0)) { /* Smoke 'em if you got 'em */ LIBSSH2_FREE(session, data); return ret; } } /* Only reached if the socket died */ return -1; }
int _libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session, libssh2_rsa_ctx *rsa, const unsigned char *hash, size_t hash_len, unsigned char **signature, size_t *signature_len) { BCRYPT_PKCS1_PADDING_INFO paddingInfo; unsigned char *data, *sig; unsigned long cbData, datalen, siglen; int ret; datalen = (unsigned long)hash_len; data = malloc(datalen); if (!data) { return -1; } paddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM; memcpy(data, hash, datalen); ret = BCryptSignHash(rsa->hKey, &paddingInfo, data, datalen, NULL, 0, &cbData, BCRYPT_PAD_PKCS1); if (BCRYPT_SUCCESS(ret)) { siglen = cbData; sig = LIBSSH2_ALLOC(session, siglen); if (sig) { ret = BCryptSignHash(rsa->hKey, &paddingInfo, data, datalen, sig, siglen, &cbData, BCRYPT_PAD_PKCS1); if (BCRYPT_SUCCESS(ret)) { *signature_len = siglen; *signature = sig; } else { LIBSSH2_FREE(session, sig); } } else ret = STATUS_NO_MEMORY; } free(data); return BCRYPT_SUCCESS(ret) ? 0 : -1; }
/* * _libssh2_packet_ask * * Scan the brigade for a matching packet type, optionally poll the socket for * a packet first */ int _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len) { LIBSSH2_PACKET *packet = session->packets.head; _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Looking for packet of type: %d", (int) packet_type); while (packet) { if (packet->data[0] == packet_type && (packet->data_len >= (match_ofs + match_len)) && (!match_buf || (memcmp(packet->data + match_ofs, match_buf, match_len) == 0))) { *data = packet->data; *data_len = packet->data_len; /* unlink struct */ if (packet->prev) { packet->prev->next = packet->next; } else { session->packets.head = packet->next; } if (packet->next) { packet->next->prev = packet->prev; } else { session->packets.tail = packet->prev; } LIBSSH2_FREE(session, packet); return 0; } packet = packet->next; } return -1; }
/* {{{ libssh2_packet_ask * Scan the brigade for a matching packet type, optionally poll the socket for a packet first */ int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, int poll_socket) { LIBSSH2_PACKET *packet = session->packets.head; if (poll_socket) { if (libssh2_packet_read(session, 0) < 0) { return -1; } } #ifdef LIBSSH2_DEBUG_TRANSPORT _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Looking for packet of type: %d", (int)packet_type); #endif while (packet) { if (packet->data[0] == packet_type && (packet->data_len >= (match_ofs + match_len)) && (!match_buf || (memcmp(packet->data + match_ofs, match_buf, match_len) == 0))) { *data = packet->data; *data_len = packet->data_len; if (packet->prev) { packet->prev->next = packet->next; } else { session->packets.head = packet->next; } if (packet->next) { packet->next->prev = packet->prev; } else { session->packets.tail = packet->prev; } LIBSSH2_FREE(session, packet); return 0; } packet = packet->next; } return -1; }