void ssh_eap_protocol_send_response(SshEapProtocol protocol, SshEap eap, SshBuffer buf) { SSH_PRECOND(eap != NULL); SSH_PRECOND(ssh_eap_isauthenticator(eap) == 0); SSH_ASSERT(ssh_eap_packet_isvalid(buf)); /* Send packet */ ssh_eap_remember_packet(eap, buf); ssh_eap_send_packet(eap, buf); }
void ssh_eap_protocol_request_token_with_args(SshEap eap, SshUInt8 eap_type, SshEapTokenType type, unsigned char *input, SshUInt16 input_len) { SshBufferStruct buf; SshEapTokenStruct token; SSH_PRECOND(eap != NULL); SSH_DEBUG(SSH_D_MIDOK,("requesting token of type %d from user %u", type, input_len)); eap->waiting_for_callback = 1; buf.dynamic = FALSE; buf.buf = (unsigned char*)&token; buf.alloc = sizeof(token); buf.offset = 0; buf.end = buf.alloc; token.token.buffer.dptr = input; token.token.buffer.len = input_len; token.type = type; ssh_eap_send_signal(eap, eap_type, SSH_EAP_SIGNAL_NEED_TOKEN, &buf); }
void* ssh_eap_protocol_get_params(SshEapProtocol protocol) { SSH_PRECOND(protocol != NULL); return protocol->params; }
void* ssh_eap_protocol_get_state(SshEapProtocol protocol) { SSH_PRECOND(protocol != NULL); return protocol->state; }
void ssh_eap_send_signal(SshEap eap, SshUInt8 type, SshEapSignal signal, SshBuffer buf) { SSH_PRECOND(eap != NULL); if (eap->destroy_pending == 1 || eap->params == NULL || eap->params->signal_cb == NULL_FNPTR) { SSH_DEBUG(SSH_D_ERROR, ("incapable of delivering signal, discarding it")); if (buf) ssh_buffer_free(buf); return; } SSH_EAP_CB(eap, eap->params->signal_cb(eap, type, signal, buf, eap->ctx)); }
SshBuffer ssh_eap_create_reply(SshEap eap, SshUInt16 len, SshUInt8 type) { SshBuffer pkt; SSH_PRECOND(eap != NULL); pkt = ssh_buffer_allocate(); if (pkt == NULL) return NULL; SSH_ASSERT(eap->id_isinit == 1); if (!ssh_eap_packet_build_hdr_with_type(pkt, SSH_EAP_CODE_REPLY, eap->id, len, type)) { ssh_buffer_free(pkt); return NULL; } return pkt; }
SshRadiusUrlStatus ssh_radius_url_add_server(SshRadiusClientServerInfo s_info, unsigned char *url) { unsigned char *scheme, *host, *port, *username, *password, *path; const unsigned char *real_port, *real_secret; Boolean res; SSH_PRECOND(url != NULL); real_port = NULL; scheme = host = port = username = password = path = NULL; res = ssh_url_parse(url, &scheme, &host, &port, &username, &password, &path); if (res == FALSE) goto fail; res = FALSE; if (scheme == NULL) goto fail; if (ssh_usstrcmp(scheme, "radius") != 0) goto fail; if (host == NULL) goto fail; real_port = (real_port != NULL ? port : (unsigned char *)"1812"); real_secret = (password != NULL ? password : (unsigned char *)""); res = ssh_radius_client_server_info_add_server(s_info, host, real_port, real_port, real_secret, ssh_ustrlen(real_secret)); fail: if (scheme != NULL) ssh_free(scheme); if (host != NULL) ssh_free(host); if (port != NULL) ssh_free(port); if (username != NULL) ssh_free(username); if (password != NULL) ssh_free(password); if (path != NULL) ssh_free(path); return res; }
unsigned long ssh_eap_protocol_get_mru(SshEapProtocol protocol, SshEap eap) { SSH_PRECOND(eap != NULL); return (eap->con != NULL ? eap->con->mru : 1400); }
Boolean ssh_eap_isauthenticator(SshEap eap) { SSH_PRECOND(eap != NULL); return (eap->is_authenticator == 1 ? TRUE : FALSE); }
void ssh_eap_protocol_master_session_key(SshEap eap, const unsigned char *session_key, size_t session_key_len) { SSH_PRECOND(eap->msk == NULL); eap->msk = ssh_memdup(session_key, session_key_len); eap->msk_len = session_key_len; }
void ssh_eap_protocol_auth_fail(SshEapProtocol protocol, SshEap eap, SshEapSignal sig, SshBuffer buf) { SshUInt8 id; SSH_PRECOND(eap != NULL); eap->method_done = 1; eap->method_ok = 0; #ifdef SSHDIST_RADIUS ssh_eap_radius_reset(eap); #endif /* SSHDIST_RADIUS */ ssh_eap_cancel_auth_timeout(eap); /* Send the packet first, and then the signal */ if (eap->is_authenticator == 1 && ssh_eap_send_failure(eap) == FALSE) { eap->id_isrecv = 0; return; } eap->id_isrecv = 0; if (protocol != NULL) { id = protocol->impl->id; } else { id = eap->previous_eap_type; } switch (sig) { case SSH_EAP_SIGNAL_AUTH_FAIL_USERNAME: break; case SSH_EAP_SIGNAL_AUTH_FAIL_NEGOTIATION: buf = NULL; break; default: buf = NULL; if (ssh_eap_isauthenticator(eap) == TRUE) sig = SSH_EAP_SIGNAL_AUTH_FAIL_REPLY; else sig = SSH_EAP_SIGNAL_AUTH_FAIL_AUTHENTICATOR; break; } ssh_eap_send_signal(eap, id, sig, buf); }
void ssh_eap_protocol_auth_ok(SshEapProtocol protocol, SshEap eap, SshEapSignal sig, SshBuffer buf) { SshUInt8 id; SSH_PRECOND(eap != NULL); eap->method_done = 1; eap->method_ok = 1; #ifdef SSHDIST_RADIUS ssh_eap_radius_reset(eap); #endif /* SSHDIST_RADIUS */ ssh_eap_cancel_auth_timeout(eap); if (protocol != NULL) { id = protocol->impl->id; } else { id = eap->previous_eap_type; } if (ssh_eap_isauthenticator(eap)) { /* Send the packet first, and then the signal */ if (ssh_eap_send_success(eap) == TRUE) { eap->id_isrecv = 0; if (sig != SSH_EAP_SIGNAL_AUTH_OK_USERNAME) { sig = SSH_EAP_SIGNAL_AUTH_AUTHENTICATOR_OK; buf = NULL; } ssh_eap_send_signal(eap, id, sig, buf); } eap->id_isrecv = 0; } else { ssh_eap_send_signal(eap, id, SSH_EAP_SIGNAL_AUTH_PEER_MAYBE_OK, NULL); } }
void *ssh_strdup (const void * p) { const char * str; char * cp; SSH_PRECOND(p != NULL); str = (const char *) p; if ((cp = (char *) ssh_malloc(strlen(str) + 1)) == NULL) return NULL; strcpy(cp, str); return (void *) cp; }
static void ssh_eap_timeout(SshEap eap) { SSH_PRECOND(eap != NULL); /* Reset the EAP instance, so that no further signals are delivered untill action by the owner of the instance. */ ssh_eap_reset(eap); /* Signal the caller that authentication has failed due to a timeout */ SSH_DEBUG(SSH_D_MIDOK,("EAP authentication timed out")); ssh_eap_send_signal(eap, eap->previous_eap_type, SSH_EAP_SIGNAL_AUTH_FAIL_TIMEOUT, NULL); }
static SshRadiusUrlStatus ssh_radius_url_parse_nas_id(unsigned char *url, unsigned char **result) { Boolean res; SshRadiusUrlStatus url_status; unsigned char *scheme, *name; SSH_PRECOND(url != NULL); /* Note that we can not detect if this failed due to an out of memory error! If we could, then we would provide more than an equivalent of FALSE/TRUE in the return code. */ res = ssh_url_parse(url, &scheme, NULL, NULL, &name, NULL, NULL); if (res == FALSE) return SSH_RADIUS_URL_MALFORMED; url_status = SSH_RADIUS_URL_INVALID_SCHEME; if (scheme == NULL) goto fail; if (ssh_usstrcmp(scheme, "radius") != 0) goto fail; ssh_free(scheme); *result = name; if (name == NULL) return SSH_RADIUS_URL_EXPECTING_NAS_ID; return SSH_RADIUS_URL_STATUS_SUCCESS; fail: if (scheme != NULL) ssh_free(scheme); if (name != NULL) ssh_free(name); *result = NULL; return url_status; }
SshRadiusUrlStatus ssh_radius_url_isok(unsigned char *url) { SshRadiusUrlAvpSetStruct avp_set; SshRadiusUrlStatus url_status; SshRadiusClientServerInfo s_info; SshRadiusClientParamsStruct params; SSH_PRECOND(url != NULL); /* Check Params specification */ url_status = ssh_radius_url_init_params(¶ms, url); if (url_status != SSH_RADIUS_URL_STATUS_SUCCESS) return url_status; ssh_radius_url_uninit_params(¶ms); /* Check server spec. */ s_info = ssh_radius_client_server_info_create(); if (s_info == NULL) return SSH_RADIUS_URL_OUT_OF_MEMORY; url_status = ssh_radius_url_add_server(s_info, url); ssh_radius_client_server_info_destroy(s_info); if (url_status != SSH_RADIUS_URL_STATUS_SUCCESS) return url_status; /* Check AVP spec */ url_status = ssh_radius_url_init_avpset(&avp_set, url); if (url_status != SSH_RADIUS_URL_STATUS_SUCCESS) return url_status; ssh_radius_url_uninit_avpset(&avp_set); return SSH_RADIUS_URL_STATUS_SUCCESS; }
void ssh_eap_send_packet(SshEap eap, SshBuffer buf) { SSH_PRECOND(eap != NULL); /* Remember the last packet we sent out */ eap->previous_eap_code = ssh_eap_packet_get_code(buf); if (ssh_eap_packet_get_length(buf) > 4) eap->previous_eap_type = ssh_eap_packet_get_type(buf); /* Assume that the eap->con has been destroyed, if we have been destroyed (which may well be the case). */ if (eap->destroy_pending == 0) { SSH_EAP_CB(eap, ssh_eap_connection_output_packet(eap->con,buf)); } }
/* Destroys the connection context. */ void tcp_connect_destroy_ctx(ConnectContext c) { SSH_DEBUG(4, ("Destroying ConnectContext...")); SSH_PRECOND(c != NULL); if (c->handle) ssh_operation_abort(c->handle); ssh_cancel_timeout(&c->timeout); ssh_free(c->local_address); ssh_free(c->host_name); ssh_free(c->host_addresses); ssh_free(c->socks_host); ssh_free(c->socks_addresses); ssh_free(c->user_name); ssh_free(c->socks_exceptions); if (c->socks_buf) ssh_buffer_free(c->socks_buf); if (c->stream) ssh_stream_destroy(c->stream); if (c->upper_handle) ssh_operation_unregister(c->upper_handle); ssh_free(c); }
/* Parses a given comma-separated list to tokens, which are stored in a SshDlList. The list is allocated and returned by this function. On error, returns NULL. */ SshDlList ssh_config_parse_list(char *string, SshParameterValidityProc function, void *context) { char *rest; char *current; SshDlList list; SSH_PRECOND(string != NULL); list = ssh_dllist_allocate(); rest = string; while (strlen(rest) != 0 && (current = ssh_name_list_get_name(rest)) != NULL) { char *temp; int i, j; rest += strlen(current); if (*rest == ',') rest++; /* strip whitespaces and non-printable characters */ temp = ssh_xcalloc(strlen(current) + 1, sizeof(char)); for (i = 0, j = 0; i < strlen(current) ; i ++) if(isascii(current[i]) && isprint(current[i]) && !isspace(current[i])) { temp[j] = current[i]; j++; } temp[j] = '\0'; ssh_xfree(current); current = temp; /* If validity function is given, invoke it to check the current parameter.*/ if (function) if ((*function)(current, context)) { ssh_xfree(current); continue; } if (ssh_dllist_add_item(list, (void *)current, SSH_DLLIST_END) != SSH_DLLIST_OK) { SSH_DEBUG(0, ("list operation gave error.")); ssh_dllist_rewind(list); while (ssh_dllist_is_empty(list)) { char *to_be_deleted; to_be_deleted = ssh_dllist_delete_current(list); ssh_xfree(to_be_deleted); } ssh_dllist_free(list); return NULL; } } return list; }
static SshRadiusUrlStatus ssh_radius_url_add_avp(SshRadiusUrlAvpSet avp_set, const SshRadiusAvpInfoStruct *avp_info, unsigned char *value, size_t value_len) { unsigned long val; SshRadiusUrlStatus url_status; SSH_PRECOND(avp_set != NULL); SSH_PRECOND(avp_info != NULL); /* Try to allow for "magic keyword" substituion for selected parameter values. */ if (avp_info->value_type == SSH_RADIUS_AVP_VALUE_INTEGER) { url_status = ssh_radius_url_add_avp_by_type(avp_set, avp_info, value, value_len); if (url_status != SSH_RADIUS_URL_STATUS_NONE) return url_status; } /* Perform setting based on type */ switch (avp_info->value_type) { case SSH_RADIUS_AVP_VALUE_TEXT: if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type, (SshUInt8 *) value, (SshUInt8)value_len) == FALSE) return SSH_RADIUS_URL_OUT_OF_MEMORY; break; case SSH_RADIUS_AVP_VALUE_TAG_INTEGER: case SSH_RADIUS_AVP_VALUE_TAG_STRING: case SSH_RADIUS_AVP_VALUE_IPV6_ADDRESS: SSH_DEBUG(SSH_D_FAIL,("TAG and IPV6 attributes not yet supported")); return SSH_RADIUS_URL_UNKNOWN_AVP_TYPE; break; case SSH_RADIUS_AVP_VALUE_TIME: case SSH_RADIUS_AVP_VALUE_INTEGER: { SshUInt8 number_buf[4]; val = (value != NULL ? ssh_ustrtol(value, NULL, 0) : 0); SSH_PUT_32BIT(number_buf, val); if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type, number_buf, 4) == FALSE) return SSH_RADIUS_URL_OUT_OF_MEMORY; } break; /* Convert IPv4 address to 32-bit integer */ case SSH_RADIUS_AVP_VALUE_ADDRESS: { SshIpAddrStruct ip_addr; SshUInt8 number_buf[4]; if (value == NULL) return SSH_RADIUS_URL_INVALID_AVP_VALUE; if (ssh_ipaddr_parse(&ip_addr, value) == FALSE) return SSH_RADIUS_URL_INVALID_AVP_VALUE; if (SSH_IP_IS4(&ip_addr) == FALSE) return SSH_RADIUS_URL_INVALID_AVP_VALUE; SSH_PUT_32BIT(number_buf, SSH_IP4_TO_INT(&ip_addr)); if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type, number_buf, 4) == FALSE) return SSH_RADIUS_URL_OUT_OF_MEMORY; } break; default: SSH_DEBUG(SSH_D_FAIL, ("Unknown RADIUS attribute value type %d!", avp_info->value_type)); return SSH_RADIUS_URL_UNKNOWN_AVP_TYPE; } return SSH_RADIUS_URL_STATUS_SUCCESS; }
Boolean ssh_radius_url_set_avpset_avp(SshRadiusUrlAvpSet avp_set, SshRadiusAvpType avp_type, SshUInt8 *buf, SshUInt8 len) { size_t i; SshUInt8 *new_buf; SshRadiusUrlAvp avp; SSH_PRECOND(avp_set != NULL); /* First see if we can get a buffer for the contents of the AVP */ avp = NULL; new_buf = NULL; if (buf != NULL) { new_buf = ssh_malloc(len); if (new_buf == NULL) return FALSE; memcpy(new_buf, buf, len); } /* .. then try to enlarge the AVP set in such a manner that it does not break if we run out of memory.. */ for (i = 0; i < avp_set->navps; i++) { if (avp_set->avp[i].type == avp_type) break; } if (i == avp_set->navps) { avp = ssh_malloc((avp_set->navps+1)*sizeof(SshRadiusUrlAvpStruct)); if (avp == NULL) return FALSE; avp_set->navps++; memcpy(avp, avp_set->avp, (avp_set->navps)*sizeof(SshRadiusUrlAvpStruct)); ssh_free(avp_set->avp); avp_set->avp = avp; avp[i].type = 0; avp[i].buf = NULL; avp[i].len = 0; } else { avp = avp_set->avp; if (avp[i].buf != NULL) ssh_free(avp[i].buf); avp[i].buf = NULL; avp[i].len = 0; avp[i].type = 0; } avp[i].buf = new_buf; avp[i].len = len; avp[i].type = avp_type; return TRUE; }
/*------------------------------------------------------------------------ Waits multiple events to occur. ------------------------------------------------------------------------*/ __inline Boolean ssh_event_wait_multiple(unsigned long event_cnt, SshEvent *events, SshWCB wcb) { unsigned int i = 0; void *wait_block = NULL; SshOsEvent *wait_objects; #ifdef _WIN32_WCE DWORD status; DWORD wait_time = INFINITE; BOOL wait_all = TRUE; #else NTSTATUS status = STATUS_SUCCESS; LARGE_INTEGER t, *pt = &t; WAIT_TYPE wait_type = WaitAll; #endif /* _WIN32_WCE */ SSH_PRECOND(events != NULL); SSH_PRECOND(event_cnt > 0 && event_cnt < SSH_EVT_WAIT_MAX_CNT); SSH_PRECOND(wcb != NULL); #ifdef _WIN32_WCE if (wcb->mode == SSH_EVT_WAIT_MODE_ANY) wait_all = FALSE; if (wcb->wait_time_ms != SSH_EVT_WAIT_INFINITE) wait_time = wcb->wait_time_ms; #else /* Set wait mode */ if (wcb->mode == SSH_EVT_WAIT_MODE_ANY) wait_type = WaitAny; /* Calculate wait timeout */ if (wcb ->wait_time_ms == SSH_EVT_WAIT_INFINITE) pt = NULL; else pt->QuadPart = (wcb->wait_time_ms * (-10000)); /* Allocate memory for wait block if not allready initialized */ if (!wcb->reserved[1]) { wait_block = wcb->reserved[1] = ssh_calloc(event_cnt, sizeof(KWAIT_BLOCK)); if (wait_block == NULL) { SSH_DEBUG(SSH_D_FAIL, ("Failed to allocate wait block")); return FALSE; } } #endif /* _WIN32_WCE */ /* Allocate memory for objects if not already initialized */ if (!wcb->reserved[0]) { wait_objects = ssh_calloc(event_cnt, sizeof(events[0]->os_event)); if (wait_objects == NULL) { SSH_DEBUG(SSH_D_FAIL, ("Failed to allocate memory for objects")); ssh_free(wait_block); return FALSE; } wcb->reserved[0] = wait_objects; /* Init object array with events that we are interested in */ for (i = 0; i < event_cnt; i++) wait_objects[i] = events[i]->os_event; } /* Wait for events to occur */ #ifdef _WIN32_WCE status = WaitForMultipleObjects(event_cnt, wcb->reserved[0], wait_all, wait_time); if ((status < WAIT_OBJECT_0) || (status >= (WAIT_OBJECT_0 + event_cnt))) { DWORD error = GetLastError(); SSH_DEBUG(SSH_D_FAIL, ("Wait failed (%08X, %08X)", status, error)); return FALSE; } #else status = KeWaitForMultipleObjects(event_cnt, wcb->reserved[0], wait_type, Executive, KernelMode, FALSE, pt, wcb->reserved[1]); /* Check wait result */ if (!NT_SUCCESS(status)) { SSH_DEBUG(SSH_D_FAIL, ("Wait failed (%08X)", status)); return FALSE; } #endif /* _WIN32_WCE */ if ((unsigned long)status < event_cnt) { /* Clear event state */ ssh_event_reset(events[status]); /* Execute possible associated event handler routine */ if (events[status]->event_cb) events[status]->event_cb(events[status]->context); } return TRUE; }
char *ssh_snlist_intersection(const char *src1, const char *src2) { int total_len1, total_len2, name_len1, name_len2, max_len1, max_len2; Boolean prev; const char *tmp; char *dest, *dest_start; SSH_PRECOND(src1 != NULL); SSH_PRECOND(src2 != NULL); /* Set up the destination buffer. */ prev = FALSE; if ((dest = ssh_malloc(strlen(src1) + 1)) == NULL) return NULL; dest_start = dest; /* Start looping the two namelists. And seek for names of same length and only then compare. */ max_len1 = strlen(src1); max_len2 = strlen(src2); for (total_len1 = 0; total_len1 < max_len1; ) { /* Get name lenght */ name_len1 = ssh_snlist_name_len(src1); /* Start inner loop */ for (tmp = src2, total_len2 = 0; total_len2 < max_len2; ) { name_len2 = ssh_snlist_name_len(tmp); if (name_len2 == name_len1) { if (memcmp(src1, tmp, name_len1) == 0) { if (prev) *dest++ = ','; prev = TRUE; memcpy(dest, src1, name_len1); dest += name_len1; break; } } total_len2 += name_len2; /* Tricky part is to notice that we need to check for terminating zero, and quit if found. */ tmp += name_len2; if (*tmp == '\0') break; /* Not zero so get past that comma. */ tmp++; } total_len1 += name_len1; src1 += name_len1; if (*src1 == '\0') break; src1++; } /* In any case place zero terminator to the namelist. */ *dest = '\0'; return dest_start; }