res_pjsip_authenticator_digest.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2013, Digium, Inc.
  5. *
  6. * Mark Michelson <mmichelson@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. #include "asterisk.h"
  19. #include <pjsip.h>
  20. #include "asterisk/res_pjsip.h"
  21. #include "asterisk/logger.h"
  22. #include "asterisk/module.h"
  23. #include "asterisk/strings.h"
  24. /*** MODULEINFO
  25. <depend>pjproject</depend>
  26. <depend>res_pjsip</depend>
  27. <support_level>core</support_level>
  28. ***/
  29. /* From the auth/realm realtime column size */
  30. #define MAX_REALM_LENGTH 40
  31. static char default_realm[MAX_REALM_LENGTH + 1];
  32. AO2_GLOBAL_OBJ_STATIC(entity_id);
  33. /*!
  34. * \brief Determine if authentication is required
  35. *
  36. * Authentication is required if the endpoint has at least one auth
  37. * section specified
  38. */
  39. static int digest_requires_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
  40. {
  41. RAII_VAR(struct ast_sip_endpoint *, artificial, ast_sip_get_artificial_endpoint(), ao2_cleanup);
  42. return endpoint == artificial || AST_VECTOR_SIZE(&endpoint->inbound_auths) > 0;
  43. }
  44. static void auth_store_cleanup(void *data)
  45. {
  46. struct ast_sip_auth **auth = data;
  47. ao2_cleanup(*auth);
  48. ast_free(data);
  49. }
  50. /*!
  51. * \brief Thread-local storage for \ref ast_sip_auth
  52. *
  53. * The PJSIP authentication API is a bit annoying. When you set
  54. * up an authentication server, you specify a lookup callback to
  55. * call into when verifying incoming credentials. The problem
  56. * with this callback is that it only gives you the realm and
  57. * authentication username. In 2.0.5, there is a new version of
  58. * the callback you can use that gives the pjsip_rx_data in
  59. * addition.
  60. *
  61. * Unfortunately, the data we actually \b need is the
  62. * \ref ast_sip_auth we are currently observing. So we have two
  63. * choices:
  64. * 1) Use the current PJSIP API and use thread-local storage
  65. * to temporarily store our SIP authentication information. Then
  66. * in the callback, we can retrieve the authentication info and
  67. * use as needed. Given our threading model, this is safe.
  68. * 2) Use the 2.0.5 API and temporarily store the authentication
  69. * information in the rdata's endpoint_info. Then in the callback,
  70. * we can retrieve the authentication info from the rdata.
  71. *
  72. * I've chosen option 1 since it does not require backporting
  73. * any APIs from future versions of PJSIP, plus I feel the
  74. * thread-local option is a bit cleaner.
  75. */
  76. AST_THREADSTORAGE_CUSTOM(auth_store, NULL, auth_store_cleanup);
  77. /*!
  78. * \brief Store shallow copy authentication information in thread-local storage
  79. */
  80. static int store_auth(const struct ast_sip_auth *auth)
  81. {
  82. const struct ast_sip_auth **pointing;
  83. pointing = ast_threadstorage_get(&auth_store, sizeof(pointing));
  84. if (!pointing) {
  85. return -1;
  86. }
  87. *pointing = auth;
  88. return 0;
  89. }
  90. /*!
  91. * \brief Remove shallow copy authentication information from thread-local storage
  92. */
  93. static int remove_auth(void)
  94. {
  95. struct ast_sip_auth **pointing;
  96. pointing = ast_threadstorage_get(&auth_store, sizeof(pointing));
  97. if (!pointing) {
  98. return -1;
  99. }
  100. *pointing = NULL;
  101. return 0;
  102. }
  103. /*!
  104. * \brief Retrieve shallow copy authentication information from thread-local storage
  105. */
  106. static const struct ast_sip_auth *get_auth(void)
  107. {
  108. struct ast_sip_auth **auth;
  109. auth = ast_threadstorage_get(&auth_store, sizeof(auth));
  110. if (auth) {
  111. return *auth;
  112. }
  113. return NULL;
  114. }
  115. /*!
  116. * \brief Lookup callback for authentication verification
  117. *
  118. * This function is called when we call pjsip_auth_srv_verify(). It
  119. * expects us to verify that the realm and account name from the
  120. * Authorization header is correct. We are then supposed to supply
  121. * a password or MD5 sum of credentials.
  122. *
  123. * \param pool A memory pool we can use for allocations
  124. * \param realm The realm from the Authorization header
  125. * \param acc_name the user from the Authorization header
  126. * \param[out] info The credentials we need to fill in
  127. * \retval PJ_SUCCESS Successful authentication
  128. * \retval other Unsuccessful
  129. */
  130. static pj_status_t digest_lookup(pj_pool_t *pool, const pj_str_t *realm,
  131. const pj_str_t *acc_name, pjsip_cred_info *info)
  132. {
  133. const struct ast_sip_auth *auth;
  134. auth = get_auth();
  135. if (!auth) {
  136. return PJSIP_SC_FORBIDDEN;
  137. }
  138. if (auth->type == AST_SIP_AUTH_TYPE_ARTIFICIAL) {
  139. return PJSIP_SC_FORBIDDEN;
  140. }
  141. if (pj_strcmp2(realm, auth->realm)) {
  142. return PJSIP_SC_FORBIDDEN;
  143. }
  144. if (pj_strcmp2(acc_name, auth->auth_user)) {
  145. return PJSIP_SC_FORBIDDEN;
  146. }
  147. pj_strdup2(pool, &info->realm, auth->realm);
  148. pj_strdup2(pool, &info->username, auth->auth_user);
  149. switch (auth->type) {
  150. case AST_SIP_AUTH_TYPE_USER_PASS:
  151. pj_strdup2(pool, &info->data, auth->auth_pass);
  152. info->data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
  153. break;
  154. case AST_SIP_AUTH_TYPE_MD5:
  155. pj_strdup2(pool, &info->data, auth->md5_creds);
  156. info->data_type = PJSIP_CRED_DATA_DIGEST;
  157. break;
  158. default:
  159. return PJSIP_SC_FORBIDDEN;
  160. }
  161. return PJ_SUCCESS;
  162. }
  163. /*!
  164. * \brief Calculate a nonce
  165. *
  166. * We use this in order to create authentication challenges. We also use this in order
  167. * to verify that an incoming request with credentials could be in response to one
  168. * of our challenges.
  169. *
  170. * The nonce is calculated from a timestamp, the source IP address, the source port, a
  171. * unique ID for us, and the realm. This helps to ensure that the incoming request
  172. * is from the same source that the nonce was calculated for. Including the realm
  173. * ensures that multiple challenges to the same request have different nonces.
  174. *
  175. * \param A UNIX timestamp expressed as a string
  176. * \param rdata The incoming request
  177. * \param realm The realm for which authentication should occur
  178. */
  179. static int build_nonce(struct ast_str **nonce, const char *timestamp, const pjsip_rx_data *rdata, const char *realm)
  180. {
  181. struct ast_str *str = ast_str_alloca(256);
  182. RAII_VAR(char *, eid, ao2_global_obj_ref(entity_id), ao2_cleanup);
  183. char hash[33];
  184. /*
  185. * Note you may be tempted to think why not include the port. The reason
  186. * is that when using TCP the port can potentially differ from before.
  187. */
  188. ast_str_append(&str, 0, "%s", timestamp);
  189. ast_str_append(&str, 0, ":%s", rdata->pkt_info.src_name);
  190. ast_str_append(&str, 0, ":%s", eid);
  191. ast_str_append(&str, 0, ":%s", realm);
  192. ast_md5_hash(hash, ast_str_buffer(str));
  193. ast_str_append(nonce, 0, "%s/%s", timestamp, hash);
  194. return 0;
  195. }
  196. /*!
  197. * \brief Ensure that a nonce on an incoming request is sane.
  198. *
  199. * The nonce in an incoming Authorization header needs to pass some scrutiny in order
  200. * for us to consider accepting it. What we do is re-build a nonce based on request
  201. * data and a realm and see if it matches the nonce they sent us.
  202. * \param candidate The nonce on an incoming request
  203. * \param rdata The incoming request
  204. * \param auth The auth credentials we are trying to match against.
  205. * \retval 0 Nonce does not pass validity checks
  206. * \retval 1 Nonce passes validity check
  207. */
  208. static int check_nonce(const char *candidate, const pjsip_rx_data *rdata, const struct ast_sip_auth *auth)
  209. {
  210. char *copy = ast_strdupa(candidate);
  211. char *timestamp = strsep(&copy, "/");
  212. int timestamp_int;
  213. time_t now = time(NULL);
  214. struct ast_str *calculated = ast_str_alloca(64);
  215. if (!copy) {
  216. /* Clearly a bad nonce! */
  217. return 0;
  218. }
  219. if (sscanf(timestamp, "%30d", &timestamp_int) != 1) {
  220. return 0;
  221. }
  222. if ((int) now - timestamp_int > auth->nonce_lifetime) {
  223. return 0;
  224. }
  225. build_nonce(&calculated, timestamp, rdata, auth->realm);
  226. ast_debug(3, "Calculated nonce %s. Actual nonce is %s\n", ast_str_buffer(calculated), candidate);
  227. if (strcmp(ast_str_buffer(calculated), candidate)) {
  228. return 0;
  229. }
  230. return 1;
  231. }
  232. static int find_challenge(const pjsip_rx_data *rdata, const struct ast_sip_auth *auth)
  233. {
  234. struct pjsip_authorization_hdr *auth_hdr = (pjsip_authorization_hdr *) &rdata->msg_info.msg->hdr;
  235. int challenge_found = 0;
  236. char nonce[64];
  237. while ((auth_hdr = (pjsip_authorization_hdr *) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION, auth_hdr->next))) {
  238. ast_copy_pj_str(nonce, &auth_hdr->credential.digest.nonce, sizeof(nonce));
  239. if (check_nonce(nonce, rdata, auth) && !pj_strcmp2(&auth_hdr->credential.digest.realm, auth->realm)) {
  240. challenge_found = 1;
  241. break;
  242. }
  243. }
  244. return challenge_found;
  245. }
  246. /*!
  247. * \brief Common code for initializing a pjsip_auth_srv
  248. */
  249. static void setup_auth_srv(pj_pool_t *pool, pjsip_auth_srv *auth_server, const char *realm)
  250. {
  251. pj_str_t realm_str;
  252. pj_cstr(&realm_str, realm);
  253. pjsip_auth_srv_init(pool, auth_server, &realm_str, digest_lookup, 0);
  254. }
  255. /*!
  256. * \brief Result of digest verification
  257. */
  258. enum digest_verify_result {
  259. /*! Authentication credentials incorrect */
  260. AUTH_FAIL,
  261. /*! Authentication credentials correct */
  262. AUTH_SUCCESS,
  263. /*! Authentication credentials correct but nonce mismatch */
  264. AUTH_STALE,
  265. /*! Authentication credentials were not provided */
  266. AUTH_NOAUTH,
  267. };
  268. /*!
  269. * \brief astobj2 callback for verifying incoming credentials
  270. *
  271. * \param auth The ast_sip_auth to check against
  272. * \param rdata The incoming request
  273. * \param pool A pool to use for the auth server
  274. * \return CMP_MATCH on successful authentication
  275. * \return 0 on failed authentication
  276. */
  277. static int verify(const struct ast_sip_auth *auth, pjsip_rx_data *rdata, pj_pool_t *pool)
  278. {
  279. pj_status_t authed;
  280. int response_code;
  281. pjsip_auth_srv auth_server;
  282. int stale = 0;
  283. if (!find_challenge(rdata, auth)) {
  284. /* Couldn't find a challenge with a sane nonce.
  285. * Nonce mismatch may just be due to staleness.
  286. */
  287. stale = 1;
  288. }
  289. setup_auth_srv(pool, &auth_server, auth->realm);
  290. store_auth(auth);
  291. authed = pjsip_auth_srv_verify(&auth_server, rdata, &response_code);
  292. remove_auth();
  293. if (authed == PJ_SUCCESS) {
  294. if (stale) {
  295. return AUTH_STALE;
  296. } else {
  297. return AUTH_SUCCESS;
  298. }
  299. }
  300. if (authed == PJSIP_EAUTHNOAUTH) {
  301. return AUTH_NOAUTH;
  302. }
  303. return AUTH_FAIL;
  304. }
  305. /*!
  306. * \brief astobj2 callback for adding digest challenges to responses
  307. *
  308. * \param realm An auth's realm to build a challenge from
  309. * \param tdata The response to add the challenge to
  310. * \param rdata The request the challenge is in response to
  311. * \param is_stale Indicates whether nonce on incoming request was stale
  312. */
  313. static void challenge(const char *realm, pjsip_tx_data *tdata, const pjsip_rx_data *rdata, int is_stale)
  314. {
  315. pj_str_t qop;
  316. pj_str_t pj_nonce;
  317. pjsip_auth_srv auth_server;
  318. struct ast_str *nonce = ast_str_alloca(256);
  319. char time_buf[32];
  320. time_t timestamp = time(NULL);
  321. snprintf(time_buf, sizeof(time_buf), "%d", (int) timestamp);
  322. build_nonce(&nonce, time_buf, rdata, realm);
  323. setup_auth_srv(tdata->pool, &auth_server, realm);
  324. pj_cstr(&pj_nonce, ast_str_buffer(nonce));
  325. pj_cstr(&qop, "auth");
  326. pjsip_auth_srv_challenge(&auth_server, &qop, &pj_nonce, NULL, is_stale ? PJ_TRUE : PJ_FALSE, tdata);
  327. }
  328. /*!
  329. * \brief Check authentication using Digest scheme
  330. *
  331. * This function will check an incoming message against configured authentication
  332. * options. If \b any of the incoming Authorization headers result in successful
  333. * authentication, then authentication is considered successful.
  334. *
  335. * \see ast_sip_check_authentication
  336. */
  337. static enum ast_sip_check_auth_result digest_check_auth(struct ast_sip_endpoint *endpoint,
  338. pjsip_rx_data *rdata, pjsip_tx_data *tdata)
  339. {
  340. struct ast_sip_auth **auths;
  341. struct ast_sip_auth **auths_shallow;
  342. enum digest_verify_result *verify_res;
  343. struct ast_sip_endpoint *artificial_endpoint;
  344. enum ast_sip_check_auth_result res;
  345. int idx;
  346. int is_artificial;
  347. int failures = 0;
  348. size_t auth_size;
  349. auth_size = AST_VECTOR_SIZE(&endpoint->inbound_auths);
  350. ast_assert(0 < auth_size);
  351. auths = ast_alloca(auth_size * sizeof(*auths));
  352. verify_res = ast_alloca(auth_size * sizeof(*verify_res));
  353. artificial_endpoint = ast_sip_get_artificial_endpoint();
  354. if (!artificial_endpoint) {
  355. /* Should not happen except possibly if we are shutting down. */
  356. return AST_SIP_AUTHENTICATION_ERROR;
  357. }
  358. is_artificial = endpoint == artificial_endpoint;
  359. ao2_ref(artificial_endpoint, -1);
  360. if (is_artificial) {
  361. ast_assert(auth_size == 1);
  362. auths[0] = ast_sip_get_artificial_auth();
  363. if (!auths[0]) {
  364. /* Should not happen except possibly if we are shutting down. */
  365. return AST_SIP_AUTHENTICATION_ERROR;
  366. }
  367. } else {
  368. memset(auths, 0, auth_size * sizeof(*auths));
  369. if (ast_sip_retrieve_auths(&endpoint->inbound_auths, auths)) {
  370. res = AST_SIP_AUTHENTICATION_ERROR;
  371. goto cleanup;
  372. }
  373. }
  374. /* Setup shallow copy of auths */
  375. if (ast_strlen_zero(default_realm)) {
  376. auths_shallow = auths;
  377. } else {
  378. /*
  379. * Set default realm on a shallow copy of the authentication
  380. * objects that don't have a realm set.
  381. */
  382. auths_shallow = ast_alloca(auth_size * sizeof(*auths_shallow));
  383. for (idx = 0; idx < auth_size; ++idx) {
  384. if (ast_strlen_zero(auths[idx]->realm)) {
  385. /*
  386. * Make a shallow copy and set the default realm on it.
  387. *
  388. * The stack allocation is OK here. Normally this will
  389. * loop one time. If you have multiple auths then you
  390. * shouldn't need more auths than the normal complement
  391. * of fingers and toes. Otherwise, you should check
  392. * your sanity for setting up your system up that way.
  393. */
  394. auths_shallow[idx] = ast_alloca(sizeof(**auths_shallow));
  395. memcpy(auths_shallow[idx], auths[idx], sizeof(**auths_shallow));
  396. *((char **) (&auths_shallow[idx]->realm)) = default_realm;
  397. ast_debug(3, "Using default realm '%s' on incoming auth '%s'.\n",
  398. default_realm, ast_sorcery_object_get_id(auths_shallow[idx]));
  399. } else {
  400. auths_shallow[idx] = auths[idx];
  401. }
  402. }
  403. }
  404. for (idx = 0; idx < auth_size; ++idx) {
  405. verify_res[idx] = verify(auths_shallow[idx], rdata, tdata->pool);
  406. if (verify_res[idx] == AUTH_SUCCESS) {
  407. res = AST_SIP_AUTHENTICATION_SUCCESS;
  408. goto cleanup;
  409. }
  410. if (verify_res[idx] == AUTH_FAIL) {
  411. failures++;
  412. }
  413. }
  414. for (idx = 0; idx < auth_size; ++idx) {
  415. challenge(auths_shallow[idx]->realm, tdata, rdata, verify_res[idx] == AUTH_STALE);
  416. }
  417. if (failures == auth_size) {
  418. res = AST_SIP_AUTHENTICATION_FAILED;
  419. } else {
  420. res = AST_SIP_AUTHENTICATION_CHALLENGE;
  421. }
  422. cleanup:
  423. ast_sip_cleanup_auths(auths, auth_size);
  424. return res;
  425. }
  426. static struct ast_sip_authenticator digest_authenticator = {
  427. .requires_authentication = digest_requires_authentication,
  428. .check_authentication = digest_check_auth,
  429. };
  430. static int build_entity_id(void)
  431. {
  432. char *eid;
  433. eid = ao2_alloc(AST_UUID_STR_LEN, NULL);
  434. if (!eid) {
  435. return -1;
  436. }
  437. ast_uuid_generate_str(eid, AST_UUID_STR_LEN);
  438. ao2_global_obj_replace_unref(entity_id, eid);
  439. ao2_ref(eid, -1);
  440. return 0;
  441. }
  442. static void global_loaded(const char *object_type)
  443. {
  444. ast_sip_get_default_realm(default_realm, sizeof(default_realm));
  445. }
  446. /*! \brief Observer which is used to update our default_realm when the global setting changes */
  447. static struct ast_sorcery_observer global_observer = {
  448. .loaded = global_loaded,
  449. };
  450. static int reload_module(void)
  451. {
  452. if (build_entity_id()) {
  453. return -1;
  454. }
  455. return 0;
  456. }
  457. static int load_module(void)
  458. {
  459. CHECK_PJSIP_MODULE_LOADED();
  460. if (build_entity_id()) {
  461. return AST_MODULE_LOAD_DECLINE;
  462. }
  463. ast_sorcery_observer_add(ast_sip_get_sorcery(), "global", &global_observer);
  464. ast_sorcery_reload_object(ast_sip_get_sorcery(), "global");
  465. if (ast_sip_register_authenticator(&digest_authenticator)) {
  466. ao2_global_obj_release(entity_id);
  467. return AST_MODULE_LOAD_DECLINE;
  468. }
  469. return AST_MODULE_LOAD_SUCCESS;
  470. }
  471. static int unload_module(void)
  472. {
  473. ast_sorcery_observer_remove(ast_sip_get_sorcery(), "global", &global_observer);
  474. ast_sip_unregister_authenticator(&digest_authenticator);
  475. ao2_global_obj_release(entity_id);
  476. return 0;
  477. }
  478. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP authentication resource",
  479. .support_level = AST_MODULE_SUPPORT_CORE,
  480. .load = load_module,
  481. .unload = unload_module,
  482. .reload = reload_module,
  483. .load_pri = AST_MODPRI_CHANNEL_DEPEND - 5,
  484. );