sterman.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /*
  2. * $Id$
  3. *
  4. * Digest Authentication - Radius support
  5. *
  6. * Copyright (C) 2001-2003 FhG Fokus
  7. *
  8. * This file is part of ser, a free SIP server.
  9. *
  10. * ser is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version
  14. *
  15. * For a license to use the ser software under conditions
  16. * other than those described here, or to purchase support for this
  17. * software, please contact iptel.org by e-mail at the following addresses:
  18. * [email protected]
  19. *
  20. * ser is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program; if not, write to the Free Software
  27. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  28. *
  29. * History:
  30. * -------
  31. * 2003-03-09: Based on digest.c from radius_auth module (janakj)
  32. */
  33. #include "../../mem/mem.h"
  34. #include "../../dprint.h"
  35. #include "../../modules/auth/api.h"
  36. #include "../../rad_dict.h"
  37. #include "../../usr_avp.h"
  38. #include "../../ut.h"
  39. #include "sterman.h"
  40. #include "authrad_mod.h"
  41. #include <stdlib.h>
  42. #include <string.h>
  43. static int add_cisco_vsa(VALUE_PAIR** send, struct sip_msg* msg)
  44. {
  45. str callid;
  46. if (!msg->callid && parse_headers(msg, HDR_CALLID_F, 0) == -1) {
  47. LOG(L_ERR, "add_cisco_vsa: Cannot parse Call-ID header field\n");
  48. return -1;
  49. }
  50. if (!msg->callid) {
  51. LOG(L_ERR, "add_cisco_vsa: Call-ID header field not found\n");
  52. return -1;
  53. }
  54. callid.len = msg->callid->body.len + 8;
  55. callid.s = pkg_malloc(callid.len);
  56. if (callid.s == NULL) {
  57. LOG(L_ERR, "add_cisco_vsa: No memory left\n");
  58. return -1;
  59. }
  60. memcpy(callid.s, "call-id=", 8);
  61. memcpy(callid.s + 8, msg->callid->body.s, msg->callid->body.len);
  62. if (rc_avpair_add(rh, send, ATTRID(attrs[A_CISCO_AVPAIR].v), callid.s,
  63. callid.len, VENDOR(attrs[A_CISCO_AVPAIR].v)) == 0) {
  64. LOG(L_ERR, "add_cisco_vsa: Unable to add Cisco-AVPair attribute\n");
  65. pkg_free(callid.s);
  66. return -1;
  67. }
  68. pkg_free(callid.s);
  69. return 0;
  70. }
  71. /*
  72. * This function creates and submits radius authentication request as per
  73. * draft-sterman-aaa-sip-00.txt. In addition, _user parameter is included
  74. * in the request as value of a SER specific attribute type SIP-URI-User,
  75. * which can be be used as a check item in the request. Service type of
  76. * the request is Authenticate-Only.
  77. */
  78. int radius_authorize_sterman(VALUE_PAIR** received, struct sip_msg* _msg, dig_cred_t* _cred, str* _method, str* _user)
  79. {
  80. static char msg[4096];
  81. VALUE_PAIR *send;
  82. UINT4 service, ser_service_type;
  83. str method, user, user_name;
  84. str *ruri;
  85. int i;
  86. send = 0;
  87. if (!(_cred && _method && _user)) {
  88. LOG(L_ERR, "radius_authorize_sterman(): Invalid parameter value\n");
  89. return -1;
  90. }
  91. method = *_method;
  92. user = *_user;
  93. /*
  94. * Add all the user digest parameters according to the qop defined.
  95. * Most devices tested only offer support for the simplest digest.
  96. */
  97. if (_cred->username.domain.len) {
  98. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_USER_NAME].v),
  99. _cred->username.whole.s, _cred->username.whole.len,
  100. VENDOR(attrs[A_USER_NAME].v))) {
  101. LOG(L_ERR, "radius_authorize_sterman(): Unable to add User-Name attribute\n");
  102. goto err;
  103. }
  104. } else {
  105. user_name.len = _cred->username.user.len + _cred->realm.len + 1;
  106. user_name.s = pkg_malloc(user_name.len);
  107. if (!user_name.s) {
  108. LOG(L_ERR, "radius_authorize_sterman(): No memory left\n");
  109. return -3;
  110. }
  111. memcpy(user_name.s, _cred->username.whole.s, _cred->username.whole.len);
  112. user_name.s[_cred->username.whole.len] = '@';
  113. memcpy(user_name.s + _cred->username.whole.len + 1, _cred->realm.s, _cred->realm.len);
  114. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_USER_NAME].v),
  115. user_name.s, user_name.len,
  116. VENDOR(attrs[A_USER_NAME].v))) {
  117. LOG(L_ERR, "sterman(): Unable to add User-Name attribute\n");
  118. pkg_free(user_name.s);
  119. goto err;
  120. }
  121. pkg_free(user_name.s);
  122. }
  123. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_USER_NAME].v),
  124. _cred->username.whole.s, _cred->username.whole.len,
  125. VENDOR(attrs[A_DIGEST_USER_NAME].v))) {
  126. LOG(L_ERR, "sterman(): Unable to add Digest-User-Name attribute\n");
  127. goto err;
  128. }
  129. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_REALM].v),
  130. _cred->realm.s, _cred->realm.len,
  131. VENDOR(attrs[A_DIGEST_REALM].v))) {
  132. LOG(L_ERR, "sterman(): Unable to add Digest-Realm attribute\n");
  133. goto err;
  134. }
  135. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_NONCE].v),
  136. _cred->nonce.s, _cred->nonce.len,
  137. VENDOR(attrs[A_DIGEST_NONCE].v))) {
  138. LOG(L_ERR, "sterman(): Unable to add Digest-Nonce attribute\n");
  139. goto err;
  140. }
  141. if (use_ruri_flag < 0 || isflagset(_msg, use_ruri_flag) != 1) {
  142. ruri = &_cred->uri;
  143. } else {
  144. ruri = GET_RURI(_msg);
  145. }
  146. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_URI].v),
  147. ruri->s, ruri->len,
  148. VENDOR(attrs[A_DIGEST_URI].v))) {
  149. LOG(L_ERR, "sterman(): Unable to add Digest-URI attribute\n");
  150. goto err;
  151. }
  152. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_METHOD].v),
  153. method.s, method.len,
  154. VENDOR(attrs[A_DIGEST_METHOD].v))) {
  155. LOG(L_ERR, "sterman(): Unable to add Digest-Method attribute\n");
  156. goto err;
  157. }
  158. /*
  159. * Add the additional authentication fields according to the QOP.
  160. */
  161. if (_cred->qop.qop_parsed == QOP_AUTH) {
  162. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_QOP].v), "auth", 4,
  163. VENDOR(attrs[A_DIGEST_QOP].v))) {
  164. LOG(L_ERR, "sterman(): Unable to add Digest-QOP attribute\n");
  165. goto err;
  166. }
  167. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_NONCE_COUNT].v),
  168. _cred->nc.s, _cred->nc.len,
  169. VENDOR(attrs[A_DIGEST_NONCE_COUNT].v))) {
  170. LOG(L_ERR, "sterman(): Unable to add Digest-CNonce-Count attribute\n");
  171. goto err;
  172. }
  173. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_CNONCE].v),
  174. _cred->cnonce.s, _cred->cnonce.len,
  175. VENDOR(attrs[A_DIGEST_CNONCE].v))) {
  176. LOG(L_ERR, "sterman(): Unable to add Digest-CNonce attribute\n");
  177. goto err;
  178. }
  179. } else if (_cred->qop.qop_parsed == QOP_AUTHINT) {
  180. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_QOP].v), "auth-int", 8,
  181. VENDOR(attrs[A_DIGEST_QOP].v))) {
  182. LOG(L_ERR, "sterman(): Unable to add Digest-QOP attribute\n");
  183. goto err;
  184. }
  185. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_NONCE_COUNT].v),
  186. _cred->nc.s, _cred->nc.len,
  187. VENDOR(attrs[A_DIGEST_NONCE_COUNT].v))) {
  188. LOG(L_ERR, "sterman(): Unable to add Digest-Nonce-Count attribute\n");
  189. goto err;
  190. }
  191. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_CNONCE].v),
  192. _cred->cnonce.s, _cred->cnonce.len,
  193. VENDOR(attrs[A_DIGEST_CNONCE].v))) {
  194. LOG(L_ERR, "sterman(): Unable to add Digest-CNonce attribute\n");
  195. goto err;
  196. }
  197. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_BODY_DIGEST].v),
  198. _cred->opaque.s, _cred->opaque.len,
  199. VENDOR(attrs[A_DIGEST_BODY_DIGEST].v))) {
  200. LOG(L_ERR, "sterman(): Unable to add Digest-Body-Digest attribute\n");
  201. goto err;
  202. }
  203. } else {
  204. /* send nothing for qop == "" */
  205. }
  206. /* Add the response... What to calculate against... */
  207. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_RESPONSE].v),
  208. _cred->response.s, _cred->response.len,
  209. VENDOR(attrs[A_DIGEST_RESPONSE].v))) {
  210. LOG(L_ERR, "sterman(): Unable to add Digest-Response attribute\n");
  211. goto err;
  212. }
  213. /* Indicate the service type, Authenticate only in our case */
  214. service = vals[V_SIP_SESSION].v;
  215. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SERVICE_TYPE].v),
  216. &service, -1,
  217. VENDOR(attrs[A_SERVICE_TYPE].v))) {
  218. LOG(L_ERR, "sterman(): Unable to add Service-Type attribute\n");
  219. goto err;
  220. }
  221. /* Indicate the service type, Authenticate only in our case */
  222. ser_service_type = vals[V_DIGEST_AUTHENTICATION].v;
  223. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_SERVICE_TYPE].v),
  224. &ser_service_type, -1,
  225. VENDOR(attrs[A_SER_SERVICE_TYPE].v))) {
  226. LOG(L_ERR, "sterman(): Unable to add SER-Service-Type attribute\n");
  227. goto err;
  228. }
  229. /* Add SIP URI as a check item */
  230. if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_URI_USER].v),
  231. user.s, user.len,
  232. VENDOR(attrs[A_SER_URI_USER].v))) {
  233. LOG(L_ERR, "sterman(): Unable to add Sip-URI-User attribute\n");
  234. goto err;
  235. }
  236. if (attrs[A_CISCO_AVPAIR].n != NULL) {
  237. if (add_cisco_vsa(&send, _msg)) {
  238. goto err;
  239. }
  240. }
  241. /* Send request */
  242. if ((i = rc_auth(rh, SIP_PORT, send, received, msg)) == OK_RC) {
  243. DBG("radius_authorize_sterman(): Success\n");
  244. rc_avpair_free(send);
  245. send = 0;
  246. return 1;
  247. } else {
  248. DBG("radius_authorize_sterman(): Failure\n");
  249. goto err;
  250. }
  251. err:
  252. if (send) rc_avpair_free(send);
  253. return -1;
  254. }