00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "../../data_lump.h"
00038 #include "../../mem/mem.h"
00039 #include "../../parser/digest/digest.h"
00040 #include "../../pvar.h"
00041 #include "../../str.h"
00042 #include "../../ut.h"
00043 #include "../../mod_fix.h"
00044 #include "auth_mod.h"
00045 #include "common.h"
00046 #include "challenge.h"
00047 #include "nonce.h"
00048 #include "index.h"
00049 #include "api.h"
00050
00051 static str auth_400_err = str_init(MESSAGE_400);
00052 static str auth_500_err = str_init(MESSAGE_500);
00053
00054
00055
00056
00057
00058 #define MESSAGE_407 "Proxy Authentication Required"
00059 #define PROXY_AUTH_CHALLENGE "Proxy-Authenticate"
00060
00061
00062
00063
00064
00065 #define MESSAGE_401 "Unauthorized"
00066 #define WWW_AUTH_CHALLENGE "WWW-Authenticate"
00067
00068
00069 #define QOP_PARAM ", qop=\"auth\""
00070 #define QOP_PARAM_LEN (sizeof(QOP_PARAM)-1)
00071 #define STALE_PARAM ", stale=true"
00072 #define STALE_PARAM_LEN (sizeof(STALE_PARAM)-1)
00073 #define DIGEST_REALM ": Digest realm=\""
00074 #define DIGEST_REALM_LEN (sizeof(DIGEST_REALM)-1)
00075 #define DIGEST_NONCE "\", nonce=\""
00076 #define DIGEST_NONCE_LEN (sizeof(DIGEST_NONCE)-1)
00077 #define DIGEST_MD5 ", algorithm=MD5"
00078 #define DIGEST_MD5_LEN (sizeof(DIGEST_MD5)-1)
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 static inline char *build_auth_hf(int _stale, str* _realm, int* _len,
00091 int _qop, char* _hf_name)
00092 {
00093
00094 int hf_name_len;
00095 char *hf, *p;
00096 int index = 0;
00097
00098 if(nonce_reuse==0)
00099 {
00100
00101 index= reserve_nonce_index();
00102 if(index == -1)
00103 {
00104 LM_ERR("no more nonces can be generated\n");
00105 return 0;
00106 }
00107 LM_DBG("nonce index= %d\n", index);
00108 }
00109
00110 *_len=hf_name_len=strlen(_hf_name);
00111 *_len+=DIGEST_REALM_LEN
00112 +_realm->len
00113 +DIGEST_NONCE_LEN
00114 +((nonce_reuse==0)?NONCE_LEN:NONCE_LEN-8)
00115 +1
00116 +((_qop)? QOP_PARAM_LEN:0)
00117 +((_stale)? STALE_PARAM_LEN : 0)
00118 #ifdef _PRINT_MD5
00119 +DIGEST_MD5_LEN
00120 #endif
00121 +CRLF_LEN ;
00122
00123 p=hf=pkg_malloc(*_len+1);
00124 if (!hf) {
00125 LM_ERR("no pkg memory left\n");
00126 *_len=0;
00127 return 0;
00128 }
00129
00130 memcpy(p, _hf_name, hf_name_len); p+=hf_name_len;
00131 memcpy(p, DIGEST_REALM, DIGEST_REALM_LEN);p+=DIGEST_REALM_LEN;
00132 memcpy(p, _realm->s, _realm->len);p+=_realm->len;
00133 memcpy(p, DIGEST_NONCE, DIGEST_NONCE_LEN);p+=DIGEST_NONCE_LEN;
00134 calc_nonce(p, time(0) + nonce_expire, index, &secret);
00135 p+=((nonce_reuse==0)?NONCE_LEN:NONCE_LEN-8);
00136 *p='"';p++;
00137 if (_qop) {
00138 memcpy(p, QOP_PARAM, QOP_PARAM_LEN);
00139 p+=QOP_PARAM_LEN;
00140 }
00141 if (_stale) {
00142 memcpy(p, STALE_PARAM, STALE_PARAM_LEN);
00143 p+=STALE_PARAM_LEN;
00144 }
00145 #ifdef _PRINT_MD5
00146 memcpy(p, DIGEST_MD5, DIGEST_MD5_LEN ); p+=DIGEST_MD5_LEN;
00147 #endif
00148 memcpy(p, CRLF, CRLF_LEN ); p+=CRLF_LEN;
00149 *p=0;
00150
00151 LM_DBG("'%s'\n", hf);
00152 return hf;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 static inline int challenge(struct sip_msg* _msg, gparam_p _realm, int _qop,
00166 int _code, char* _message, char* _challenge_msg)
00167 {
00168 int auth_hf_len;
00169 struct hdr_field* h;
00170 auth_body_t* cred = 0;
00171 char *auth_hf;
00172 int ret;
00173 hdr_types_t hftype = 0;
00174 struct sip_uri *uri;
00175 str realm;
00176 str reason;
00177
00178 switch(_code) {
00179 case 401:
00180 get_authorized_cred(_msg->authorization, &h);
00181 hftype = HDR_AUTHORIZATION_T;
00182 break;
00183 case 407:
00184 get_authorized_cred(_msg->proxy_auth, &h);
00185 hftype = HDR_PROXYAUTH_T;
00186 break;
00187 }
00188
00189 if (h) cred = (auth_body_t*)(h->parsed);
00190
00191 if(fixup_get_svalue(_msg, _realm, &realm)!=0)
00192 {
00193 LM_ERR("invalid realm parameter");
00194 if (send_resp(_msg, 500, &auth_500_err, 0, 0)==-1)
00195 return -1;
00196 else
00197 return 0;
00198 }
00199 if (realm.len == 0) {
00200 if (get_realm(_msg, hftype, &uri) < 0) {
00201 LM_ERR("failed to extract URI\n");
00202 if (send_resp(_msg, 400, &auth_400_err, 0, 0) == -1) {
00203 LM_ERR("failed to send the response\n");
00204 return -1;
00205 }
00206 return 0;
00207 }
00208
00209 realm = uri->host;
00210 strip_realm(&realm);
00211 }
00212
00213 auth_hf = build_auth_hf((cred ? cred->stale : 0), &realm,
00214 &auth_hf_len, _qop, _challenge_msg);
00215 if (!auth_hf) {
00216 LM_ERR("failed to generate nonce\n");
00217 return -1;
00218 }
00219
00220 reason.s = _message;
00221 reason.len = strlen(_message);
00222 ret = send_resp(_msg, _code, &reason, auth_hf, auth_hf_len);
00223 if (auth_hf) pkg_free(auth_hf);
00224 if (ret == -1) {
00225 LM_ERR("failed to send the response\n");
00226 return -1;
00227 }
00228
00229 return 0;
00230 }
00231
00232
00233
00234 int www_challenge(struct sip_msg* _msg, char* _realm, char* _qop)
00235 {
00236
00237
00238
00239
00240
00241
00242 return challenge(_msg, (gparam_p)_realm, (int)(long)_qop, 401,
00243 MESSAGE_401, WWW_AUTH_CHALLENGE);
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 int proxy_challenge(struct sip_msg* _msg, char* _realm, char* _qop)
00256 {
00257 return challenge(_msg, (gparam_p)_realm, (int)(long)_qop, 407,
00258 MESSAGE_407, PROXY_AUTH_CHALLENGE);
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 int consume_credentials(struct sip_msg* _m, char* _s1, char* _s2)
00270 {
00271 struct hdr_field* h;
00272 int len;
00273
00274 get_authorized_cred(_m->authorization, &h);
00275 if (!h) {
00276 get_authorized_cred(_m->proxy_auth, &h);
00277 if (!h) {
00278 if (_m->REQ_METHOD!=METHOD_ACK
00279 && _m->REQ_METHOD!=METHOD_CANCEL) {
00280 LM_ERR("no authorized credentials found (error in scripts)\n");
00281 }
00282 return -1;
00283 }
00284 }
00285
00286 len=h->len;
00287
00288 if (del_lump(_m, h->name.s - _m->buf, len, 0) == 0) {
00289 LM_ERR("can't remove credentials\n");
00290 return -1;
00291 }
00292
00293 return 1;
00294 }