mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	chan_iax2: Improve authentication debugging.
Improves and adds some logging to make it easier for users to debug authentication issues. Resolves: #286
This commit is contained in:
		| @@ -398,6 +398,47 @@ static int (*iax2_regfunk)(const char *username, int onoff) = NULL; | ||||
| #define DEFAULT_FREQ_OK		60 * 1000	/* How often to check for the host to be up */ | ||||
| #define DEFAULT_FREQ_NOTOK	10 * 1000	/* How often to check, if the host is down... */ | ||||
|  | ||||
| /*! \brief Name of effective auth method */ | ||||
| static const char *auth_method_labels[] = { | ||||
|     [0] = "none", | ||||
|     [IAX_AUTH_PLAINTEXT] = "plaintext", | ||||
|     [IAX_AUTH_MD5] = "MD5", | ||||
|     [IAX_AUTH_RSA] = "RSA", | ||||
| }; | ||||
|  | ||||
| /* Max length is length of |RSA|MD5|plaintext (18 + 1 for NUL = 19) */ | ||||
| #define AUTH_METHOD_NAMES_BUFSIZE 19 | ||||
|  | ||||
| /*! | ||||
|  * \brief Get names of all auth methods | ||||
|  * \param Bit field of auth methods | ||||
|  * \param[out] buf Buffer into which to write the names. Must be of size AUTH_METHOD_NAMES_BUFSIZE. | ||||
|  * \return Auth methods name | ||||
|  */ | ||||
| static char *auth_method_names(int authmethods, char *restrict buf) | ||||
| { | ||||
| 	char *pos = buf; | ||||
|  | ||||
| 	*pos = '\0'; | ||||
|  | ||||
| 	if (authmethods & IAX_AUTH_RSA) { | ||||
| 		pos += sprintf(pos, "|RSA"); | ||||
| 	} | ||||
| 	if (authmethods & IAX_AUTH_MD5) { | ||||
| 		pos += sprintf(pos, "|MD5"); | ||||
| 	} | ||||
| 	if (authmethods & IAX_AUTH_PLAINTEXT) { | ||||
| 		pos += sprintf(pos, "|plaintext"); | ||||
| 	} | ||||
|  | ||||
| 	if (pos == buf) { /* No auth methods */ | ||||
| 		strcpy(buf, "none"); | ||||
| 		return buf; | ||||
| 	} | ||||
|  | ||||
| 	return buf + 1; /* Skip leading | */ | ||||
| } | ||||
|  | ||||
| /* if a pvt has encryption setup done and is running on the call */ | ||||
| #define IAX_CALLENCRYPTED(pvt) \ | ||||
| 	(ast_test_flag64(pvt, IAX_ENCRYPTED) && ast_test_flag64(pvt, IAX_KEYPOPULATED)) | ||||
| @@ -825,6 +866,8 @@ struct chan_iax2_pvt { | ||||
| 	int authrej; | ||||
| 	/*! permitted authentication methods */ | ||||
| 	int authmethods; | ||||
| 	/*! effective authentication method */ | ||||
| 	int eff_auth_method; | ||||
| 	/*! permitted encryption methods */ | ||||
| 	int encmethods; | ||||
| 	/*! Encryption AES-128 Key */ | ||||
| @@ -8189,7 +8232,7 @@ static int authenticate_verify(struct chan_iax2_pvt *p, struct iax_ies *ies) | ||||
| 		user = user_unref(user); | ||||
| 	} | ||||
| 	if (ast_test_flag64(p, IAX_FORCE_ENCRYPT) && !p->encmethods) { | ||||
| 		ast_log(LOG_NOTICE, "Call Terminated, Incoming call is unencrypted while force encrypt is enabled.\n"); | ||||
| 		ast_log(LOG_WARNING, "Call Terminated, incoming call is unencrypted while force encrypt is enabled.\n"); | ||||
| 		return res; | ||||
| 	} | ||||
| 	if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED)) | ||||
| @@ -8215,12 +8258,17 @@ static int authenticate_verify(struct chan_iax2_pvt *p, struct iax_ies *ies) | ||||
| 			key = ast_key_get(keyn, AST_KEY_PUBLIC); | ||||
| 			if (key && !ast_check_signature(key, p->challenge, rsasecret)) { | ||||
| 				res = 0; | ||||
| 				p->eff_auth_method = IAX_AUTH_RSA; | ||||
| 				break; | ||||
| 			} else if (!key) | ||||
| 				ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn); | ||||
| 			} else if (!key) { | ||||
| 				ast_log(LOG_WARNING, "Requested inkey '%s' for RSA authentication does not exist\n", keyn); | ||||
| 			} | ||||
| 			keyn = strsep(&stringp, ":"); | ||||
| 		} | ||||
| 		ast_free(tmpkey); | ||||
| 		if (res && authdebug) { | ||||
| 			ast_log(LOG_WARNING, "No RSA public keys on file matched incoming call\n"); | ||||
| 		} | ||||
| 	} else if (p->authmethods & IAX_AUTH_MD5) { | ||||
| 		struct MD5Context md5; | ||||
| 		unsigned char digest[16]; | ||||
| @@ -8237,12 +8285,19 @@ static int authenticate_verify(struct chan_iax2_pvt *p, struct iax_ies *ies) | ||||
| 				sprintf(requeststr + (x << 1), "%02hhx", digest[x]); /* safe */ | ||||
| 			if (!strcasecmp(requeststr, md5secret)) { | ||||
| 				res = 0; | ||||
| 				p->eff_auth_method = IAX_AUTH_MD5; | ||||
| 				break; | ||||
| 			} else if (authdebug) { | ||||
| 				ast_log(LOG_WARNING, "MD5 secret mismatch\n"); | ||||
| 			} | ||||
| 		} | ||||
| 	} else if (p->authmethods & IAX_AUTH_PLAINTEXT) { | ||||
| 		if (!strcmp(secret, p->secret)) | ||||
| 		if (!strcmp(secret, p->secret)) { | ||||
| 			res = 0; | ||||
| 			p->eff_auth_method = IAX_AUTH_PLAINTEXT; | ||||
| 		} else if (authdebug) { | ||||
| 			ast_log(LOG_WARNING, "Plaintext secret mismatch\n"); | ||||
| 		} | ||||
| 	} | ||||
| 	return res; | ||||
| } | ||||
| @@ -8417,22 +8472,25 @@ static int authenticate(const char *challenge, const char *secret, const char *k | ||||
| 	if (!ast_strlen_zero(keyn)) { | ||||
| 		if (!(authmethods & IAX_AUTH_RSA)) { | ||||
| 			if (ast_strlen_zero(secret)) { | ||||
| 				ast_log(LOG_NOTICE, "Asked to authenticate to %s with an RSA key, but they don't allow RSA authentication\n", ast_sockaddr_stringify_addr(addr)); | ||||
| 				ast_log(LOG_WARNING, "Asked to authenticate to %s with an RSA key, but they don't allow RSA authentication\n", ast_sockaddr_stringify_addr(addr)); | ||||
| 			} | ||||
| 		} else if (ast_strlen_zero(challenge)) { | ||||
| 			ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_sockaddr_stringify_addr(addr)); | ||||
| 			ast_log(LOG_WARNING, "No challenge provided for RSA authentication to %s\n", ast_sockaddr_stringify_addr(addr)); | ||||
| 		} else { | ||||
| 			char sig[256]; | ||||
| 			struct ast_key *key; | ||||
| 			key = ast_key_get(keyn, AST_KEY_PRIVATE); | ||||
| 			if (!key) { | ||||
| 				ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn); | ||||
| 				ast_log(LOG_WARNING, "Unable to find private key '%s'\n", keyn); | ||||
| 			} else { | ||||
| 				if (ast_sign(key, (char*)challenge, sig)) { | ||||
| 					ast_log(LOG_NOTICE, "Unable to sign challenge with key\n"); | ||||
| 					ast_log(LOG_WARNING, "Unable to sign challenge with key\n"); | ||||
| 					res = -1; | ||||
| 				} else { | ||||
| 					iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig); | ||||
| 					if (pvt) { | ||||
| 						pvt->eff_auth_method = IAX_AUTH_RSA; | ||||
| 					} | ||||
| 					res = 0; | ||||
| 				} | ||||
| 			} | ||||
| @@ -8465,11 +8523,15 @@ static int authenticate(const char *challenge, const char *secret, const char *k | ||||
| 				sprintf(digres + (x << 1),  "%02hhx", digest[x]); /* safe */ | ||||
| 			if (pvt) { | ||||
| 				build_encryption_keys(digest, pvt); | ||||
| 				pvt->eff_auth_method = IAX_AUTH_MD5; | ||||
| 			} | ||||
| 			iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres); | ||||
| 			res = 0; | ||||
| 		} else if (authmethods & IAX_AUTH_PLAINTEXT) { | ||||
| 			iax_ie_append_str(ied, IAX_IE_PASSWORD, secret); | ||||
| 			if (pvt) { | ||||
| 				pvt->eff_auth_method = IAX_AUTH_PLAINTEXT; | ||||
| 			} | ||||
| 			res = 0; | ||||
| 		} else | ||||
| 			ast_log(LOG_WARNING, "No way to send secret to peer '%s' (their methods: %d)\n", ast_sockaddr_stringify_addr(addr), authmethods); | ||||
| @@ -11311,7 +11373,7 @@ static int socket_process_helper(struct iax2_thread *thread) | ||||
| 				} | ||||
| 				if (authenticate_verify(iaxs[fr->callno], &ies)) { | ||||
| 					if (authdebug) | ||||
| 						ast_log(LOG_NOTICE, "Host %s failed to authenticate as %s\n", ast_sockaddr_stringify(&addr), | ||||
| 						ast_log(LOG_WARNING, "Host %s failed to authenticate as %s\n", ast_sockaddr_stringify(&addr), | ||||
| 								iaxs[fr->callno]->username); | ||||
| 					memset(&ied0, 0, sizeof(ied0)); | ||||
| 					auth_fail(fr->callno, IAX_COMMAND_REJECT); | ||||
| @@ -11324,7 +11386,7 @@ static int socket_process_helper(struct iax2_thread *thread) | ||||
| 					exists = 0; | ||||
| 				if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { | ||||
| 					if (authdebug) | ||||
| 						ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", | ||||
| 						ast_log(LOG_WARNING, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", | ||||
| 								ast_sockaddr_stringify(&addr), | ||||
| 								iaxs[fr->callno]->exten, | ||||
| 								iaxs[fr->callno]->context); | ||||
| @@ -11379,12 +11441,12 @@ static int socket_process_helper(struct iax2_thread *thread) | ||||
| 						if (!format) { | ||||
| 							if (authdebug) { | ||||
| 								if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) { | ||||
| 									ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested '%s' incompatible with our capability '%s'.\n", | ||||
| 									ast_log(LOG_WARNING, "Rejected connect attempt from %s, requested '%s' incompatible with our capability '%s'.\n", | ||||
| 											ast_sockaddr_stringify(&addr), | ||||
| 										iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf), | ||||
| 										iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf)); | ||||
| 								} else { | ||||
| 									ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n", | ||||
| 									ast_log(LOG_WARNING, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n", | ||||
| 										ast_sockaddr_stringify(&addr), | ||||
| 										iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf), | ||||
| 										iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf), | ||||
| @@ -11437,12 +11499,12 @@ static int socket_process_helper(struct iax2_thread *thread) | ||||
| 									iax2_getformatname_multiple(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, &cap_buf)); | ||||
| 								if (authdebug) { | ||||
| 									if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) { | ||||
| 										ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested '%s' incompatible with our capability '%s'.\n", | ||||
| 										ast_log(LOG_WARNING, "Rejected connect attempt from %s, requested '%s' incompatible with our capability '%s'.\n", | ||||
| 											ast_sockaddr_stringify(&addr), | ||||
| 											iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf), | ||||
| 											iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf)); | ||||
| 									} else { | ||||
| 										ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n", | ||||
| 										ast_log(LOG_WARNING, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n", | ||||
| 											ast_sockaddr_stringify(&addr), | ||||
| 											iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf), | ||||
| 											iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf), | ||||
| @@ -11466,8 +11528,12 @@ static int socket_process_helper(struct iax2_thread *thread) | ||||
| 						iax_ie_append_versioned_uint64(&ied1, IAX_IE_FORMAT2, 0, format); | ||||
| 						send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); | ||||
| 						if (strcmp(iaxs[fr->callno]->exten, "TBD")) { | ||||
| 							char authmethodnames[AUTH_METHOD_NAMES_BUFSIZE]; | ||||
| 							ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); | ||||
| 							ast_verb(3, "Accepting AUTHENTICATED call from %s:\n" | ||||
| 											"%srequested auth methods = (%s),\n" | ||||
| 											"%sactual auth method = %s,\n" | ||||
| 											"%sencrypted = %s,\n" | ||||
| 											"%srequested format = %s,\n" | ||||
| 											"%srequested prefs = %s,\n" | ||||
| 											"%sactual format = %s,\n" | ||||
| @@ -11475,6 +11541,12 @@ static int socket_process_helper(struct iax2_thread *thread) | ||||
| 											"%spriority = %s\n", | ||||
| 											ast_sockaddr_stringify(&addr), | ||||
| 											VERBOSE_PREFIX_4, | ||||
| 											auth_method_names(iaxs[fr->callno]->authmethods, authmethodnames), | ||||
| 											VERBOSE_PREFIX_4, | ||||
| 											auth_method_labels[iaxs[fr->callno]->eff_auth_method], | ||||
| 											VERBOSE_PREFIX_4, | ||||
| 											IAX_CALLENCRYPTED(iaxs[fr->callno]) ? "yes" : "no", | ||||
| 											VERBOSE_PREFIX_4, | ||||
| 											iax2_getformatname(iaxs[fr->callno]->peerformat), | ||||
| 											VERBOSE_PREFIX_4, | ||||
| 											caller_pref_buf, | ||||
| @@ -11543,7 +11615,7 @@ immediatedial: | ||||
| 					ast_string_field_set(iaxs[fr->callno], exten, ies.called_number ? ies.called_number : "s"); | ||||
| 					if (!ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num)) { | ||||
| 						if (authdebug) | ||||
| 							ast_log(LOG_NOTICE, "Rejected dial attempt from %s, request '%s@%s' does not exist\n", | ||||
| 							ast_log(LOG_WARNING, "Rejected dial attempt from %s, request '%s@%s' does not exist\n", | ||||
| 									ast_sockaddr_stringify(&addr), | ||||
| 									iaxs[fr->callno]->exten, | ||||
| 									iaxs[fr->callno]->context); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user