static bool ch_ir_tokenizer_does_token_contain_only_numerals( uint8_t *puc_token) { bool b_only_numerals = false; uint8_t uc_c = 0; uint32_t ui_i = 0; if (NULL == puc_token) { CH_IR_LOG_MED("Invalid Args"); goto CLEAN_RETURN; } ui_i = pal_strlen (puc_token) - 1; while (ui_i > 0) { uc_c = puc_token [ui_i]; if (uc_c < '0' || uc_c > '9') { break; } ui_i--; } if (0 == ui_i) { b_only_numerals = true; } CLEAN_RETURN: return b_only_numerals; }
pal_regex_t * bgp_regcomp (char *regstr) { /* Convert _ character to generic regular expression. */ int i, j; int len; int magic = 0; char *magic_str; int magic_str_len; char magic_regexp[] = "(^|[,{}() ]|$)"; int ret; pal_regex_t *regex; len = pal_strlen (regstr); for (i = 0; i < len; i++) if (regstr[i] == '_') magic++; magic_str_len = len + (14 * magic) + 1; magic_str = XMALLOC (MTYPE_TMP, magic_str_len); regex = XMALLOC (MTYPE_TMP, sizeof (pal_regex_t)); for (i = 0, j = 0; i < len; i++) { if (regstr[i] == '_') { pal_mem_cpy (magic_str + j, magic_regexp, pal_strlen (magic_regexp)); j += pal_strlen (magic_regexp); } else magic_str[j++] = regstr[i]; } magic_str[j] = '\0'; ret = pal_regcomp (regex, magic_str, REG_EXTENDED); XFREE (MTYPE_TMP, magic_str); if (ret != 0) { XFREE (MTYPE_TMP, regex); return NULL; } return regex; }
// -------------------------------------------------------------------------- // // void ExtractChallenge(tChallenge *c, char *String) { char *s, *e, *Token, *Value; int len; memset(c, 0, sizeof(tChallenge)); Token = (char*) pal_malloc( pal_strlen(String)+1 ); Value = (char*) pal_malloc( pal_strlen(String)+1 ); *Token=*Value=0; for(s=e=String; ; e++) { if(*e== ',' || *e == '\r' || *e == '\n' || *e==0) { if(s!=e) { if(*Token && (*Value==0)) { len = (int)((char *)e-(char *)s); /* Chop the quotes */ if((*s == '"') && len) { s++; len--; } if((s[len-1] == '"') && len) len--; if(len) memcpy(Value, s, len); Value[len] = 0; } if(*Token && *Value) { InsertInChallegeStruct(c, Token,Value); *Value = *Token = 0; } } if(*e == 0) break; s = ++e; } if((*e=='=' || *e== ',' || *e == '\r' || *e == '\n' || *e==0) && (*Token == 0) && (e != s)) { len = (int)((char *)e-(char *)s); memcpy(Token, s, len); Token[len] = 0; if(*e == 0) break; s = ++e; } } pal_free( Token ); pal_free( Value ); }
ssize_t NetTCP6Printf( pal_socket_t sock, char *out, size_t pl, char *Format, ... ) { va_list argp; size_t Length; char Data[1024]; va_start(argp, Format); pal_vsnprintf(Data, sizeof Data, Format, argp); va_end(argp); Length = pal_strlen(Data); if( NetTCP6Write(sock, Data, pal_strlen(Data)) != Length ) { return 0; } return NetTCP6Read(sock, out, pl); }
sint32_t NetUDPPrintf(pal_socket_t sock, char *out, sint32_t ol, char *Format, ...) { va_list argp; char Data[1024]; va_start(argp, Format); pal_vsnprintf(Data, sizeof Data, Format, argp); va_end(argp); return NetUDPReadWrite(sock, Data, pal_strlen(Data), out, ol); }
static HM_RET_E hm_get_hash_from_node_data ( HM_CTXT_X *px_hm_ctxt, HM_NODE_DATA_X *px_node_data, uint32_t *pui_hash) { HM_RET_E e_error = eHM_RET_FAILURE; uint32_t ui_key_len = 0; uint8_t *puc_key_buf = NULL; if ((NULL == px_hm_ctxt) || (NULL == px_node_data) || (NULL == pui_hash)) { HM_LOG_MED("Invalid Args"); e_error = eLIST_RET_INVALID_ARGS; goto CLEAN_RETURN; } if (px_hm_ctxt->x_init_params.e_hm_key_type != px_node_data->e_hm_key_type) { HM_LOG_MED("Invalid Args"); e_error = eLIST_RET_INVALID_ARGS; goto CLEAN_RETURN; } switch (px_node_data->e_hm_key_type) { case eHM_KEY_TYPE_INT: { ui_key_len = sizeof(px_node_data->u_hm_key.ui_uint_key); puc_key_buf = (uint8_t *) &(px_node_data->u_hm_key.ui_uint_key); break; } case eHM_KEY_TYPE_STRING: { ui_key_len = pal_strlen (px_node_data->u_hm_key.puc_str_key); puc_key_buf = px_node_data->u_hm_key.puc_str_key; break; } default: { break; } } e_error = hm_gen_hash_from_buf (px_hm_ctxt, puc_key_buf, ui_key_len, pui_hash); if (eHM_RET_SUCCESS != e_error) { HM_LOG_MED("hashmap_gen_hash_from_buf failed: %d", e_error); } CLEAN_RETURN: return e_error; }
/****************************** LOCAL FUNCTIONS *******************************/ void ch_ir_indexer_truncate_trailing_whitespace( uint8_t *puc_string) { uint32_t ui_len = 0; uint32_t ui_i = 0; ui_len = pal_strlen (puc_string); if (1 == ui_len) { if (' ' == puc_string [0] || '\t' == puc_string [0] || '\n' == puc_string [0] || '\r' == puc_string [0]) { puc_string [0] = '\0'; } return; } while (ui_i < ui_len) { if (' ' == puc_string [ui_i] || '\t' == puc_string [ui_i] || '\n' == puc_string [ui_i] || '\r' == puc_string [ui_i]) { ui_i++; continue; } else { (void) pal_memmove (&(puc_string [0]), &(puc_string [ui_i]), (ui_len - ui_i + 1)); break; } } ui_len = ui_len - ui_i - 1; while (ui_len >= 0) { if (' ' == puc_string [ui_len] || '\t' == puc_string [ui_len] || '\n' == puc_string [ui_len] || '\r' == puc_string [ui_len]) { ui_len--; continue; } else { puc_string [ui_len + 1] = '\0'; break; } } }
HM_NODE_DATA_X *hm_alloc_node ( HM_NODE_DATA_X *px_node_data) { HM_NODE_DATA_X *px_new_node = NULL; uint32_t ui_key_len = 0; if (NULL == px_node_data) { HM_LOG_MED("Invalid Args"); goto CLEAN_RETURN; } px_new_node = pal_malloc (sizeof(HM_NODE_DATA_X), NULL); if (NULL == px_new_node) { HM_LOG_MED("pal_malloc failed"); goto CLEAN_RETURN; } (void) pal_memmove(px_new_node, px_node_data, sizeof (*px_new_node)); if (eHM_KEY_TYPE_STRING == px_node_data->e_hm_key_type) { ui_key_len = pal_strlen (px_node_data->u_hm_key.puc_str_key); ui_key_len = ui_key_len + 1; px_new_node->u_hm_key.puc_str_key = pal_malloc (ui_key_len, NULL); if (NULL == px_new_node->u_hm_key.puc_str_key) { pal_free (px_new_node); px_new_node = NULL; goto CLEAN_RETURN; } (void) pal_strncpy (px_new_node->u_hm_key.puc_str_key, px_node_data->u_hm_key.puc_str_key, ui_key_len); } CLEAN_RETURN: return px_new_node; }
void set_tsp_env_variables( const tConf* pConfig, const tTunnel* pTunnelInfo ) { char buffer[8]; // Specify log verbosity (MAXIMAL). pal_snprintf( buffer, sizeof buffer, "%d", LOG_LEVEL_MAX ); tspSetEnv("TSP_VERBOSE", buffer, 1); // Specify Gateway6 Client installation directory. tspSetEnv("TSP_HOME_DIR", TspHomeDir, 1); // Specify the tunnel mode. tspSetEnv("TSP_TUNNEL_MODE", pTunnelInfo->type, 1); // Specify host type {router, host} tspSetEnv("TSP_HOST_TYPE", pConfig->host_type, 1); // Specify tunnel interface, for setup. if (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6V4) == 0 ) { tspSetEnv("TSP_TUNNEL_INTERFACE", pConfig->if_tunnel_v6v4, 1); gTunnelInfo.eTunnelType = TUNTYPE_V6V4; } else if (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6UDPV4) == 0 ) { tspSetEnv("TSP_TUNNEL_INTERFACE", pConfig->if_tunnel_v6udpv4, 1); gTunnelInfo.eTunnelType = TUNTYPE_V6UDPV4; } #ifdef V4V6_SUPPORT else if (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V4V6) == 0 ) { tspSetEnv("TSP_TUNNEL_INTERFACE", pConfig->if_tunnel_v4v6, 1); gTunnelInfo.eTunnelType = TUNTYPE_V4V6; } #endif /* V4V6_SUPPORT */ // Specify what interface will be used for routing advertizement, // if enabled. tspSetEnv("TSP_HOME_INTERFACE", pConfig->if_prefix, 1); // Specify local endpoint IPv4 address tspSetEnv("TSP_CLIENT_ADDRESS_IPV4", pTunnelInfo->client_address_ipv4, 1); gTunnelInfo.szIPV4AddrLocalEndpoint = pTunnelInfo->client_address_ipv4; // Specify local endpoint IPv6 address tspSetEnv("TSP_CLIENT_ADDRESS_IPV6", pTunnelInfo->client_address_ipv6, 1); gTunnelInfo.szIPV6AddrLocalEndpoint = pTunnelInfo->client_address_ipv6; // Specify local endpoint domain name if( pTunnelInfo->client_dns_name != NULL) { tspSetEnv("TSP_CLIENT_DNS_NAME", pTunnelInfo->client_dns_name, 1); gTunnelInfo.szUserDomain = pTunnelInfo->client_dns_name; } // Specify remote endpoint IPv4 address. tspSetEnv("TSP_SERVER_ADDRESS_IPV4", pTunnelInfo->server_address_ipv4, 1); gTunnelInfo.szIPV4AddrRemoteEndpoint = pTunnelInfo->server_address_ipv4; // Specify remote endpoint IPv6 address. tspSetEnv("TSP_SERVER_ADDRESS_IPV6", pTunnelInfo->server_address_ipv6, 1); gTunnelInfo.szIPV6AddrRemoteEndpoint = pTunnelInfo->server_address_ipv6; // Specify prefix for tunnel endpoint. if ((pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6V4) == 0) || (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6UDPV4) == 0)) tspSetEnv("TSP_TUNNEL_PREFIXLEN", "128", 1); #ifdef V4V6_SUPPORT else tspSetEnv("TSP_TUNNEL_PREFIXLEN", "32", 1); #endif /* V4V6_SUPPORT */ // Free and clear delegated prefix from tunnel info. if( gTunnelInfo.szDelegatedPrefix != NULL ) { pal_free( gTunnelInfo.szDelegatedPrefix ); gTunnelInfo.szDelegatedPrefix = NULL; } // Have we been allocated a prefix for routing advertizement..? if( pTunnelInfo->prefix != NULL ) { char chPrefix[128]; size_t len, sep; /* Compute the number of characters that are significant out of the prefix. */ /* This is meaningful only for IPv6 prefixes; no contraction is possible for IPv4. */ if ((pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6V4) == 0) || (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6UDPV4) == 0)) { len = (atoi(pTunnelInfo->prefix_length) % 16) ? (atoi(pTunnelInfo->prefix_length) / 16 + 1) * 4 : atoi(pTunnelInfo->prefix_length) / 16 * 4; sep = (atoi(pTunnelInfo->prefix_length) % 16) ? (atoi(pTunnelInfo->prefix_length) / 16) : (atoi(pTunnelInfo->prefix_length) / 16) -1; } else { len = pal_strlen( pTunnelInfo->prefix ); sep = 0; } memset(chPrefix, 0, 128); memcpy(chPrefix, pTunnelInfo->prefix, len+sep); // Specify delegated prefix for routing advertizement, if enabled. tspSetEnv("TSP_PREFIX", chPrefix, 1); gTunnelInfo.szDelegatedPrefix = (char*) pal_malloc( pal_strlen(chPrefix) + 10/*To append prefix_length*/ ); strcpy( gTunnelInfo.szDelegatedPrefix, chPrefix ); // Specify prefix length for routing advertizement, if enabled. tspSetEnv("TSP_PREFIXLEN", pTunnelInfo->prefix_length, 1); strcat( gTunnelInfo.szDelegatedPrefix, "/" ); strcat( gTunnelInfo.szDelegatedPrefix, pTunnelInfo->prefix_length ); } }
static int is_dsakey_in_keyfile(DSA *dsa_1, char *host, char *filename) { FILE *fp = NULL; char *line_buf = NULL; char *str = NULL; char *str_base64 = NULL; Buffer keyfile_buf; BIGNUM *bn_p = NULL; BIGNUM *bn_q = NULL; BIGNUM *bn_g = NULL; BIGNUM *bn_pub_key = NULL; int ret = 1; size_t str_size = 0; int i; if (!dsa_1 || !host || !filename) return 0; memset(&keyfile_buf, 0, sizeof(keyfile_buf)); /* Open the keyfile */ if ( (fp = fopen(filename, "r")) == NULL) { /* no key file */ ret = 1; goto is_dsakey_in_keyfile_cleanup; } /* Get memory for a line buffer */ if ( (line_buf = pal_malloc(sizeof(char) * 4096)) == NULL) { ret = 0; goto is_dsakey_in_keyfile_cleanup; } while (freadline(line_buf, 4095, fp) != EOF) { int len; str_base64 = strtok(line_buf, " "); if (strcmp(host, str_base64) != 0) continue; /* We got a match on the hostname * Now we assemble a DSA object * with what we have in the buffer */ str_base64 = strtok(NULL, " "); if (strcmp("ssh-dss", str_base64) != 0) continue; /* We got a match on the key type as well, going on */ str_base64 = strtok(NULL, " "); /* * Get the base64 data * and discard ssh-dss first */ str_size = pal_strlen(str_base64) * sizeof(char); if ( (str = pal_malloc(str_size)) == NULL) { ret = 0; goto is_dsakey_in_keyfile_cleanup; } if ( (len = base64decode(str, str_base64)) < 1) { ret = 0; goto is_dsakey_in_keyfile_cleanup; } /* Fill a buffer structure with this data */ buffer_init(&keyfile_buf); if (keyfile_buf.buf == NULL) { ret = 0; goto is_dsakey_in_keyfile_cleanup; } buffer_append(&keyfile_buf, str, str_size); /* Now get some BN filled with the data * from the buffer and compare * those with what we got in the incoming * dsa object. */ bn_p = BN_new(); bn_q = BN_new(); bn_g = BN_new(); bn_pub_key = BN_new(); if (bn_p == NULL || bn_q == NULL || bn_g == NULL || bn_pub_key == NULL) { ret = 0; goto is_dsakey_in_keyfile_cleanup; } /* String is skipped XXX */ buffer_get_string(&keyfile_buf, (unsigned int*)&i); // Bogus i returns the string length, not used buffer_get_bignum(&keyfile_buf, bn_p); buffer_get_bignum(&keyfile_buf, bn_q); buffer_get_bignum(&keyfile_buf, bn_g); buffer_get_bignum(&keyfile_buf, bn_pub_key); if ( !BN_cmp(dsa_1->p, bn_p) && !BN_cmp(dsa_1->q, bn_q) && !BN_cmp(dsa_1->g, bn_g) && !BN_cmp(dsa_1->pub_key, bn_pub_key) ) ret = 2; else ret = 3; } is_dsakey_in_keyfile_cleanup: if (str) pal_free(str); if (line_buf) pal_free(line_buf); if (fp) fclose(fp); if (bn_p) BN_clear_free(bn_p); if (bn_q) BN_clear_free(bn_q); if (bn_g) BN_clear_free(bn_g); if (bn_pub_key) BN_clear_free(bn_pub_key); if (keyfile_buf.buf) buffer_free(&keyfile_buf); return ret; }
// -------------------------------------------------------------------------- // Function : tspAuthenticate // // Synopsys: Will authenticate a session with the broker. // // Description: // First, we'll try to find the most secure common authentication method. // Once the authentication method has been chosen, the authentication // process is initiated with the broker. // // Arguments: (only local-specific arguments are listed here) // cap: bitfield [IN], The authentication methods suported by the broker. // conf: tConf* [IN], The global configuration object. // // Return values: // A gogoc_status status. // // -------------------------------------------------------------------------- gogoc_status tspAuthenticate(pal_socket_t socket, tCapability cap, net_tools_t *nt, tConf *conf, tBrokerList **broker_list, int version_index) { gogoc_status status = make_status(CTX_TSPAUTHENTICATION, ERR_NO_COMMON_AUTHENTICATION); tCapability Mechanism; // Get mechanism, depending on requested authentication method. if( pal_strcasecmp( conf->auth_method, "any" ) == 0 ) Mechanism = AUTH_ANY; else Mechanism = tspSetCapability("AUTH", conf->auth_method); if( pal_strcasecmp( conf->auth_method, "anonymous" ) != 0 ) { // Try the most secure authentication methods first: #ifndef NO_OPENSSL if( Mechanism & cap & AUTH_PASSDSS_3DES_1 ) { Display(LOG_LEVEL_3, ELInfo, "tspAuthenticate", GOGO_STR_USING_AUTH_PASSDSS_3DES_1); status = AuthPASSDSS_3DES_1(socket, nt, conf, broker_list); goto EndAuthenticate; } #endif if( Mechanism & cap & AUTH_DIGEST_MD5 ) { Display(LOG_LEVEL_3, ELInfo, "tspAuthenticate", GOGO_STR_USING_AUTH_DIGEST_MD5); status = AuthDIGEST_MD5(socket, nt, conf, broker_list, version_index); goto EndAuthenticate; } if( Mechanism & cap & AUTH_PLAIN ) { Display(LOG_LEVEL_3, ELInfo, "tspAuthenticate", GOGO_STR_USING_AUTH_PLAIN); status = AuthPLAIN(socket, nt, conf, broker_list); goto EndAuthenticate; } } else { // Finally, try anonymous if possible. if( Mechanism & cap & AUTH_ANONYMOUS ) { Display(LOG_LEVEL_3, ELInfo, "tspAuthenticate", GOGO_STR_USING_AUTH_ANONYMOUS); status = AuthANONYMOUS(socket, nt, conf, broker_list); goto EndAuthenticate; } } EndAuthenticate: if( status_number(status) == ERR_NO_COMMON_AUTHENTICATION ) { const char* szStrings[] = { "Server Authentication Capabilities: ", "Your Configured Authentication: " }; size_t nWritten; char bufDisplay[256]; // Display server authentication capabilities. pal_snprintf( bufDisplay, sizeof(bufDisplay), "%s", szStrings[0] ); nWritten = pal_strlen( szStrings[0] ); tspFormatCapabilities( bufDisplay + nWritten, sizeof(bufDisplay) - nWritten, cap ); Display( LOG_LEVEL_1, ELWarning, "tspAuthenticate", bufDisplay ); // Display user authentication choice. pal_snprintf( bufDisplay, sizeof(bufDisplay), "%s", szStrings[1] ); nWritten = pal_strlen( szStrings[1] ); tspFormatCapabilities( bufDisplay + nWritten, sizeof(bufDisplay) - nWritten, Mechanism ); Display( LOG_LEVEL_1, ELWarning, "tspAuthenticate", bufDisplay ); // Failed to find a common authentication method. Display(LOG_LEVEL_1, ELError, "tspAuthenticate", STR_TSP_NO_COMMON_AUTHENTICATION); } return status; }
// -------------------------------------------------------------------------- // AuthDIGEST_MD5: Performs a Digest-MD5 authentication with the server. // gogoc_status AuthDIGEST_MD5(pal_socket_t socket, net_tools_t *nt, tConf *conf, tBrokerList **broker_list, int version_index) { char Buffer[4096], Response[33], cResponse[33], *ChallengeString; char string[] = "AUTHENTICATE DIGEST-MD5\r\n"; char BufferIn[REDIRECT_RECEIVE_BUFFER_SIZE]; time_t cnonce = pal_time(NULL); tChallenge c; sint32_t tsp_status; // Send authentication mode. memset(BufferIn, 0, sizeof(BufferIn)); if( nt->netsendrecv(socket, string, sizeof(string), BufferIn, sizeof(BufferIn)) == -1 ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_NET_FAIL_RW_SOCKET); return make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); } tsp_status = tspGetStatusCode(BufferIn); // Check if the reply status indicated a broker redirection. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(BufferIn, conf, broker_list) == TSP_REDIRECT_OK ) { // Return a REDIRECT event. return make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION); } else { // Redirect error. return make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION); } } // Check for error in status. if( tsp_status == TSP_PROTOCOL_AUTH_FAILED ) { // Failed authentication. Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_TSP_AUTH_FAILED_USER, conf->userid); return make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); } // Allocate memory for challenge string. if( (ChallengeString = pal_malloc(pal_strlen(BufferIn) + 1)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } base64decode(ChallengeString, BufferIn); ExtractChallenge(&c, ChallengeString); pal_free(ChallengeString); { /*-----------------------------------------------------------*/ /* Extract from : RFC 2831 Digest SASL Mechanism Let H(s) be the 16 octet MD5 hash [RFC 1321] of the octet string s. Let KD(k, s) be H({k, ":", s}), i.e., the 16 octet hash of the string k, a colon and the string s. Let HEX(n) be the representation of the 16 octet MD5 hash n as a string of 32 hex digits (with alphabetic characters always in lower case, since MD5 is case sensitive). response-value = HEX( KD ( HEX(H(A1)), { nonce-value, ":" nc-value, ":", cnonce-value, ":", qop-value, ":", HEX(H(A2)) })) If authzid is not specified, then A1 is A1 = { H( { username-value, ":", realm-value, ":", passwd } ), ":", nonce-value, ":", cnonce-value } If the "qop" directive's value is "auth", then A2 is: A2 = { "AUTHENTICATE:", digest-uri-value } */ char *A1_1Fmt = "%s:%s:%s", #ifndef WIN32 *A1Fmt = ":%s:%lu", *ChallRespFmt = "%s:%s:00000001:%lu:%s:%s", *ResponseFmt = "charset=%s,username=\"%s\",realm=\"%s\",nonce=\"%s\",nc=00000001,cnonce=\"%lu\",digest-uri=\"tsp/%s\",response=%s,qop=auth", #else // 64 bit version. *A1Fmt = ":%s:%I64d", *ChallRespFmt = "%s:%s:00000001:%I64d:%s:%s", *ResponseFmt = "charset=%s,username=\"%s\",realm=\"%s\",nonce=\"%s\",nc=00000001,cnonce=\"%I64d\",digest-uri=\"tsp/%s\",response=%s,qop=auth", #endif *A2Fmt = "%s:tsp/%s", A1[33], A1_1[33], A2[33], cA2[33], *String; size_t len; /*-----------------------------------------------------------*/ /* Build HEX(H(A2)) & HEX(H(cA2)) */ len = pal_strlen(A2Fmt) + 12 /* AUTHENTICATE */ + pal_strlen(conf->server) + 1; if( (String = pal_malloc(len)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } pal_snprintf(String, len, A2Fmt, "AUTHENTICATE", conf->server); #if defined(_DEBUG) || defined(DEBUG) printf("A2 = %s\n", String); #endif strncpy(A2, md5(String, pal_strlen(String)), 33); pal_snprintf(String, len, A2Fmt, "", conf->server); #if defined(_DEBUG) || defined(DEBUG) printf("cA2 = %s\n", String); #endif strncpy(cA2, md5(String, pal_strlen(String)), 33); pal_free(String); /*-----------------------------------------------------------*/ /* Build HEX(H(A1)) */ /* A1_1 = { username-value, ":", realm-value, ":", passwd } */ /* A1 = { H( A1_1 ), ":", nonce-value, ":", cnonce-value } */ len = pal_strlen(A1_1Fmt) + pal_strlen(conf->userid) + pal_strlen(c.realm) + pal_strlen(conf->passwd) + 1; if( (String = pal_malloc(len)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } pal_snprintf(String, len, A1_1Fmt, conf->userid, c.realm, conf->passwd); #if defined(_DEBUG) || defined(DEBUG) printf("A1_1 = %s\n", String); #endif md5digest(String, pal_strlen(String), A1_1); pal_free(String); len = 16 /* A1_1 */ + 1 + pal_strlen(c.nonce) + 16 /* cnonce */ + 1; if( (String = pal_malloc(len)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } memcpy(String, A1_1, 16); pal_snprintf(String + 16, len - 16, A1Fmt, c.nonce, cnonce); #ifdef SUPPORT_MD5_BUG1455 A1_1[16] = '\0'; if ((pal_strlen(A1_1) < 16) && !((pal_strlen(TSPProtoVerStr[version_index]) > 5) || (strcmp(TSPProtoVerStr[version_index], CLIENT_VERSION_STRING_2_0_0) > 0))) strncpy(A1, md5(String, pal_strlen(String)), 33); else #endif /* SUPPORT_MD5_BUG1455 */ strncpy(A1, md5(String, 16 + pal_strlen(String + 16)), 33); pal_free(String); #if defined(_DEBUG) || defined(DEBUG) printf("A1 = [%s]\n", A1); #endif /*-----------------------------------------------------------*/ /* Build server's and client's challenge responses */ len = pal_strlen(ChallRespFmt) + 32 /* md5(A1) */ + pal_strlen(c.nonce) +16 /* cnonce */ + pal_strlen(c.qop) + 32 /* md5(A2) */ + 1; if((String = pal_malloc(len)) == NULL) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } pal_snprintf(String, len, ChallRespFmt, A1, c.nonce, cnonce, c.qop, A2); #if defined(_DEBUG) || defined(DEBUG) printf("Response = [%s]\n", String); #endif strncpy(Response, md5(String, pal_strlen(String)), 33); #if defined(_DEBUG) || defined(DEBUG) printf("MD5 Response = %s\n", Response); #endif pal_snprintf(String, len, ChallRespFmt, A1, c.nonce, cnonce, c.qop, cA2); #if defined(_DEBUG) || defined(DEBUG) printf("cResponse = [%s]\n", String); #endif strncpy(cResponse, md5(String, pal_strlen(String)), 33); #if defined(_DEBUG) || defined(DEBUG) printf("MD5 cResponse = %s\n", cResponse); #endif pal_free(String); /*-----------------------------------------------------------*/ /* Build Response */ { char userid[512]; // UserId is theorically limited to 253 chars. char * cc; size_t i; // Escape malicious " and \ from conf->userid. for(cc=conf->userid, i=0; *cc && i<512; cc++, i++) { // Prepend a backslash (\). if( *cc == '"' || *cc == '\\' ) userid[i++] = '\\'; // Copy character. userid[i] = *cc; } userid[i] = '\0'; len = pal_strlen(ResponseFmt) + pal_strlen(c.charset) + pal_strlen(userid) + pal_strlen(c.realm) + pal_strlen(c.nonce) + 16 /*cnonce*/ + pal_strlen(conf->server) + 32 /* md5 response */; if( (String = pal_malloc(len)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } pal_snprintf(String, len, ResponseFmt, c.charset, userid, c.realm, c.nonce, cnonce, conf->server, Response); memset(Buffer, 0, sizeof(Buffer)); base64encode(Buffer, String, (int)pal_strlen(String)); pal_free(String); } } // Send authentication data. memset(BufferIn, 0, sizeof(BufferIn)); if( nt->netprintf(socket, BufferIn, sizeof(BufferIn), "%s\r\n", Buffer) == -1 ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_NET_FAIL_W_SOCKET); return make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); } tsp_status = tspGetStatusCode(BufferIn); // Check if the reply status indicated a broker redirection. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(BufferIn, conf, broker_list) == TSP_REDIRECT_OK ) { // Return a REDIRECT event. return make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION); } else { // Redirect error. return make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION); } } /*-----------------------------------------------------------*/ /* Verify server response */ if( tsp_status == TSP_PROTOCOL_AUTH_FAILED ) { // Failed authentication. Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_TSP_AUTH_FAILED_USER, conf->userid); return make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); } if( (ChallengeString = pal_malloc(pal_strlen(BufferIn) + 1)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } base64decode(ChallengeString, BufferIn); ExtractChallenge(&c, ChallengeString); pal_free(ChallengeString); if( memcmp(c.rspauth, cResponse, 32) ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_MISC_INVALID_MD5_RESPONSE); return make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); } // Receive reply. if( nt->netrecv(socket, Buffer, sizeof(Buffer) ) == -1 ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_NET_FAIL_R_SOCKET); return make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); } tsp_status = tspGetStatusCode(Buffer); // Check if the reply status indicated a broker redirection. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(Buffer, conf, broker_list) == TSP_REDIRECT_OK ) { // Return a REDIRECT event. return make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION); } else { // Redirect error. return make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION); } } // Check if authentication was successful. switch( tsp_status ) { case TSP_PROTOCOL_SUCCESS: break; case TSP_PROTOCOL_AUTH_FAILED: Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_TSP_AUTH_FAILED_USER, conf->userid); return make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); default: Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_TSP_UNKNOWN_ERR_AUTH_FAILED, tspGetTspStatusStr(tsp_status)); return make_status(CTX_TSPAUTHENTICATION, ERR_TSP_GENERIC_ERROR); } // Successful MD5 authentication. return make_status(CTX_TSPAUTHENTICATION, SUCCESS); }
/* Calculate the roundtrip time to a brokre using a TSP echo request */ tRedirectStatus timeEchoRequestReply(pal_socket_t sfd, char *address, rttengine_stat_t *engine, uint32_t *distance) { char data_in[ECHO_REQUEST_IN_BUF_SIZE]; char data_out[ECHO_REQUEST_OUT_BUF_SIZE]; sint32_t data_in_size = 0; size_t data_out_size = 0; rudp_msghdr_t *imh = NULL; rudp_msghdr_t *omh = NULL; void *om = NULL; void *im = NULL; sint32_t length_sent = 0; sint32_t ret = 0; fd_set fs; struct timeval tv_select; /* The receive buffer is empty */ memset(data_in, 0, sizeof(data_in)); /* The send buffer contains the "ECHO REQUEST" command */ pal_snprintf(data_out, sizeof(data_out), ECHO_REQUEST_COMMAND); /* Calculate the buffer sizes */ data_in_size = sizeof(data_in); data_out_size = pal_strlen(data_out); /* Prepare RUDP messages */ im = internal_prepare_message(&imh, data_in_size); om = internal_prepare_message(&omh, data_out_size); /* A NULL message is an error */ if ((im == NULL) || (om == NULL)) { rttengine_deinit(engine, im, om); *distance += ECHO_REQUEST_ERROR_ADJUST; Display(LOG_LEVEL_1, ELError, "timeEchoRequestReply", GOGO_STR_RDR_ERROR_PREPARING_RUDP_MSG, address); return TSP_REDIRECT_ECHO_REQUEST_ERROR; } /* Zero them out */ memset(im, 0, data_in_size); memset(om, 0, data_out_size); /* Copy the outgoing data to the data part of the outgoing message */ memcpy((char*)om + sizeof(rudp_msghdr_t), data_out, data_out_size); /* Set the outgoing message's sequence number */ omh->sequence = htonl(engine->sequence++ | 0xf0000000); send_loop: /* Fail if we have reached the maximum number of echo request attempts */ if (engine->retries == ECHO_REQUEST_ATTEMPTS) { rttengine_deinit(engine, im, om); *distance += ECHO_REQUEST_TIMEOUT_ADJUST; Display(LOG_LEVEL_3, ELWarning, "timeEchoRequestReply", GOGO_STR_RDR_MAX_ECHO_REPLY_ATTEMPTS, ECHO_REQUEST_ATTEMPTS, address); return TSP_REDIRECT_ECHO_REQUEST_TIMEOUT; } /* Set the timestamp for the outgoing message */ omh->timestamp = htonl(internal_get_timestamp(engine)); /* Try to send the outgoing message */ Display(LOG_LEVEL_3, ELInfo, "timeEchoRequestReply", GOGO_STR_RDR_SENDING_ECHO_REQUEST, (engine->retries + 1), address); if ((length_sent = send(sfd, om, (sint32_t)(data_out_size + sizeof(rudp_msghdr_t)), 0)) == -1) { rttengine_deinit(engine, im, om); *distance += ECHO_REQUEST_ERROR_ADJUST; Display(LOG_LEVEL_1, ELError, "timeEchoRequestReply", GOGO_STR_RDR_SEND_ECHO_REQUEST_FAILED, address); return TSP_REDIRECT_ECHO_REQUEST_ERROR; } /* Set the timeout for the select */ /* This is the maximum time we will wait for an echo reply */ tv_select.tv_sec = ECHO_REQUEST_TIMEOUT / 1000; tv_select.tv_usec = (ECHO_REQUEST_TIMEOUT % 1000) * 1000; select_loop: FD_ZERO(&fs); FD_SET(sfd, &fs); Display(LOG_LEVEL_3, ELInfo, "timeEchoRequestReply", GOGO_STR_RDR_WAITING_ECHO_REPLY, address); /* Wait on the socket set */ ret = select((sint32_t)sfd + 1, &fs, NULL, NULL, &tv_select); switch(ret) { /* Select timed out, try again */ case 0: Display(LOG_LEVEL_3, ELWarning, "timeEchoRequestReply", GOGO_STR_RDR_WAITING_ECHO_REPLY_TIMEOUT, address); engine->retries++; goto send_loop; /* Ok, select got something */ case 1: Display(LOG_LEVEL_3, ELWarning, "timeEchoRequestReply", GOGO_STR_RDR_RECEIVING_RUDP_MESSAGE, address); /* Receive the incoming data, and store it in the incoming message */ ret = recv(sfd, im, (sizeof(rudp_msghdr_t) + data_in_size), 0); /* This is a fatal read error */ if (ret == -1) { rttengine_deinit(engine, im, om); *distance += ECHO_REQUEST_ERROR_ADJUST; Display(LOG_LEVEL_1, ELError, "timeEchoRequestReply", GOGO_STR_RDR_ERR_RECEIVING_RUDP_FROM, address); return TSP_REDIRECT_ECHO_REQUEST_ERROR; } /* If we have the same sequence number, this is the message we want */ if (imh->sequence == omh->sequence) { *distance += internal_get_timestamp(engine) - ntohl(omh->timestamp); ret = ret - sizeof(rudp_msghdr_t); Display(LOG_LEVEL_3, ELInfo, "timeEchoRequestReply", GOGO_STR_RDR_RECEIVED_RUDP_OK, address); break; } /* If the sequence numbers are different, see if we get something else */ else { Display(LOG_LEVEL_3, ELWarning, "timeEchoRequestReply", GOGO_STR_RDR_RECV_RUDP_SEQ_DIFFERS, address); goto select_loop; } /* This is an unknown error */ default: rttengine_deinit(engine, im, om); *distance += ECHO_REQUEST_ERROR_ADJUST; Display(LOG_LEVEL_1, ELError, "timeEchoRequestReply", GOGO_STR_RDR_ERR_WAITING_ECHO_REPLY, address); return TSP_REDIRECT_ECHO_REQUEST_ERROR; } /* Update the stat engine */ rttengine_update(engine, (internal_get_timestamp(engine) - ntohl(imh->timestamp))); /* Copy the data part of the incoming message to the receiving buffer */ memcpy(data_in, (char*)im + sizeof(rudp_msghdr_t), ret); /* Free the messages */ internal_discard_message(im); internal_discard_message(om); engine->retries = 0; /* Validate that we got the right answer from the broker */ if (tspGetStatusCode(data_in) != ECHO_REQUEST_SUCCESS_STATUS) { Display(LOG_LEVEL_1, ELError, "timeEchoRequestReply", GOGO_STR_RDR_RCV_UNEXPECTED_ECHO_REPLY, address, data_in); return TSP_REDIRECT_ECHO_REQUEST_ERROR; } Display(LOG_LEVEL_3, ELInfo, "timeEchoRequestReply", GOGO_STR_RDR_RCV_EXPECTED_ECHO_REPLY, address, data_in); return TSP_REDIRECT_OK; }
// -------------------------------------------------------------------------- // tspGetCapabilities: // gogoc_status tspGetCapabilities(pal_socket_t socket, net_tools_t *nt, tCapability *capability, int version_index, tConf *conf, tBrokerList **broker_list) { char dataout[256]; char datain[REDIRECT_RECEIVE_BUFFER_SIZE]; sint32_t tsp_status; gogoc_status status = make_status(CTX_TSPCAPABILITIES, SUCCESS); memset( datain, 0, sizeof(datain) ); pal_snprintf(dataout, sizeof(dataout), "VERSION=%s\r\n", TSPProtoVerStr[version_index]); // Send TSP version to the server. Server should reply with the capabilities. if( nt->netsendrecv(socket, dataout, pal_strlen(dataout), datain, (sint32_t)sizeof(datain)) == -1 ) { // Error reading/writing to the socket. return make_status(CTX_TSPCAPABILITIES, ERR_SOCKET_IO); } // Check if we received the TSP capabilities. if( memcmp("CAPABILITY ", datain, 11) == 0 ) { // Extract the capabilities. *capability = tspExtractCapability(datain); } else { // Retrieve the TSP status from the reply. tsp_status = tspGetStatusCode(datain); // Check if it is a redirect TSP status. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(datain, conf, broker_list) == TSP_REDIRECT_OK ) { // REDIRECT event. status = make_status(CTX_TSPCAPABILITIES, EVNT_BROKER_REDIRECTION); } else { // Redirect error. status = make_status(CTX_TSPCAPABILITIES, ERR_BROKER_REDIRECTION); } } else { switch( tsp_status ) { case TSP_PROTOCOL_SERVER_TOO_BUSY: // Ze server iz too busy. Display(LOG_LEVEL_1, ELWarning, "tspGetCapabilities", STR_TSP_SERVER_TOO_BUSY); status = make_status(CTX_TSPCAPABILITIES, ERR_TSP_SERVER_TOO_BUSY); break; case TSP_PROTOCOL_UNSUP_TSP_VER: // The status was an invalid TSP version. Display(LOG_LEVEL_1, ELWarning, "tspGetCapabilities", STR_TSP_INVALID_VERSION, TSPProtoVerStr[version_index]); status = make_status(CTX_TSPCAPABILITIES, ERR_INVAL_TSP_VERSION); break; default: // Unknown / unexpected TSP error occurred. Display(LOG_LEVEL_1, ELError, "tspGetCapabilities", STR_TSP_GEN_ERROR, tsp_status, tspGetTspStatusStr(tsp_status)); status = make_status(CTX_TSPCAPABILITIES, ERR_TSP_GENERIC_ERROR); break; } Display(LOG_LEVEL_1, ELError, "tspGetCapabilities", STR_TSP_GETCAPABILITIES_ERROR); } } // Successful operation. return status; }