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 #include "string.h"
00030 #include "ctype.h"
00031
00032 #include "../../dprint.h"
00033 #include "../../str.h"
00034 #include "../../mem/mem.h"
00035
00036 #include "auth_hdr.h"
00037 #include "auth.h"
00038
00039
00040 #define AUTHENTICATE_MD5 (1<<0)
00041 #define AUTHENTICATE_MD5SESS (1<<1)
00042 #define AUTHENTICATE_STALE (1<<2)
00043
00044 #define AUTHENTICATE_DIGEST_S "Digest"
00045 #define AUTHENTICATE_DIGEST_LEN (sizeof(AUTHENTICATE_DIGEST_S)-1)
00046
00047 #define LOWER1B(_n) \
00048 ((_n)|0x20)
00049 #define LOWER4B(_n) \
00050 ((_n)|0x20202020)
00051 #define GET4B(_p) \
00052 ((*(_p)<<24) + (*(_p+1)<<16) + (*(_p+2)<<8) + *(_p+3))
00053 #define GET3B(_p) \
00054 ((*(_p)<<24) + (*(_p+1)<<16) + (*(_p+2)<<8) + 0xff)
00055
00056 #define CASE_5B(_hex4,_c5, _new_state, _quoted) \
00057 case _hex4: \
00058 if (p+5<end && LOWER1B(*(p+4))==_c5 ) \
00059 { \
00060 p+=5; \
00061 state = _new_state; \
00062 quoted_val = _quoted; \
00063 } else { \
00064 p+=4; \
00065 } \
00066 break;
00067
00068 #define CASE_6B(_hex4,_c5,_c6, _new_state, _quoted) \
00069 case _hex4: \
00070 if (p+6<end && LOWER1B(*(p+4))==_c5 && LOWER1B(*(p+5))==_c6) \
00071 { \
00072 p+=6; \
00073 state = _new_state; \
00074 quoted_val = _quoted; \
00075 } else { \
00076 p+=4; \
00077 } \
00078 break;
00079
00080 #define OTHER_STATE 0
00081 #define QOP_STATE 1
00082 #define REALM_STATE 2
00083 #define NONCE_STATE 3
00084 #define STALE_STATE 4
00085 #define DOMAIN_STATE 5
00086 #define OPAQUE_STATE 6
00087 #define ALGORITHM_STATE 7
00088
00089
00090
00091 int parse_authenticate_body( str *body, struct authenticate_body *auth)
00092 {
00093 char *p;
00094 char *end;
00095 int n;
00096 int state;
00097 str name;
00098 str val;
00099 int quoted_val;
00100
00101 if (body->s==0 || *body->s==0 )
00102 {
00103 LM_ERR("empty body\n");
00104 goto error;
00105 }
00106
00107 memset( auth, 0, sizeof(struct authenticate_body));
00108 p = body->s;
00109 end = body->s + body->len;
00110
00111
00112 while (p<end && isspace((int)*p)) p++;
00113 if (p+AUTHENTICATE_DIGEST_LEN>=end )
00114 goto parse_error;
00115 if (strncmp(p,AUTHENTICATE_DIGEST_S,AUTHENTICATE_DIGEST_LEN)!=0)
00116 goto parse_error;
00117 p += AUTHENTICATE_DIGEST_LEN;
00118 if (!isspace((int)*p))
00119 goto parse_error;
00120 p++;
00121 while (p<end && isspace((int)*p)) p++;
00122 if (p==end)
00123 goto parse_error;
00124
00125 while (p<end)
00126 {
00127 state = OTHER_STATE;
00128 quoted_val = 0;
00129
00130 name.s = p;
00131 if (p+4<end)
00132 {
00133 n = LOWER4B( GET4B(p) );
00134 switch(n)
00135 {
00136 CASE_5B( 0x7265616c, 'm', REALM_STATE, 1);
00137 CASE_5B( 0x6e6f6e63, 'e', NONCE_STATE, 1);
00138 CASE_5B( 0x7374616c, 'e', STALE_STATE, 0);
00139 CASE_6B( 0x646f6d62, 'i', 'n', DOMAIN_STATE, 1);
00140 CASE_6B( 0x6f706171, 'u', 'e', OPAQUE_STATE, 1);
00141 case 0x616c676f:
00142 if (p+9<end && LOWER4B(GET4B(p+4))==0x72697468
00143 && LOWER1B(*(p+8))=='m' )
00144 {
00145 p+=9;
00146 state = ALGORITHM_STATE;
00147 } else {
00148 p+=4;
00149 }
00150 break;
00151 default:
00152 if ((n|0xff)==0x716f70ff)
00153 {
00154 state = QOP_STATE;
00155 p+=3;
00156 }
00157 }
00158 } else if (p+3<end) {
00159 n = LOWER4B( GET3B(p) );
00160 if (n==0x716f70ff)
00161 {
00162 p+=3;
00163 state = QOP_STATE;
00164 }
00165 }
00166
00167
00168 for( n=0 ; p<end&&!isspace((int)*p)&&*p!='=' ; n++,p++ );
00169 if (p==end)
00170 goto parse_error;
00171 if (n!=0)
00172 state = OTHER_STATE;
00173 name.len = p-name.s;
00174
00175 while (p<end && isspace((int)*p)) p++;
00176 if (p==end || *p!='=')
00177 goto parse_error;
00178 p++;
00179
00180 while (p<end && isspace((int)*p)) p++;
00181 if (p+1>=end || (quoted_val && *p!='\"'))
00182 goto parse_error;
00183 if (!quoted_val && *p=='\"')
00184 quoted_val = 1;
00185 if (quoted_val)
00186 {
00187 val.s = ++p;
00188 while (p<end && *p!='\"')
00189 p++;
00190 if (p==end)
00191 goto error;
00192 } else {
00193 val.s = p;
00194 while (p<end && !isspace((int)*p) && *p!=',')
00195 p++;
00196 }
00197 val.len = p - val.s;
00198 if (val.len==0)
00199 val.s = 0;
00200
00201 p += quoted_val;
00202 while (p<end && isspace((int)*p)) p++;
00203 if (p<end && *p==',')
00204 {
00205 p++;
00206 while (p<end && isspace((int)*p)) p++;
00207 }
00208
00209 LM_DBG("<%.*s>=\"%.*s\" state=%d\n",
00210 name.len,name.s,val.len,val.s,state);
00211
00212
00213 switch (state)
00214 {
00215 case QOP_STATE:
00216 auth->qop = val;
00217 if(val.len>=4 && !strncmp(val.s, "auth", 4))
00218 auth->flags |= QOP_AUTH;
00219 break;
00220 case REALM_STATE:
00221 auth->realm = val;
00222 break;
00223 case NONCE_STATE:
00224 auth->nonce = val;
00225 break;
00226 case DOMAIN_STATE:
00227 auth->domain = val;
00228 break;
00229 case OPAQUE_STATE:
00230 auth->opaque = val;
00231 break;
00232 case ALGORITHM_STATE:
00233 if (val.len==3)
00234 {
00235 if ( LOWER4B(GET3B(val.s))==0x6d6435ff)
00236 auth->flags |= AUTHENTICATE_MD5;
00237 } else {
00238 LM_ERR("unsupported algorithm \"%.*s\"\n",val.len,val.s);
00239 goto error;
00240 }
00241 break;
00242 case STALE_STATE:
00243 if (val.len==4 && LOWER4B(GET4B(val.s))==0x74727565)
00244 {
00245 auth->flags |= AUTHENTICATE_STALE;
00246 } else if ( !(val.len==5 && LOWER1B(val.s[4])=='e' &&
00247 LOWER4B(GET4B(val.s))==0x66616c73) )
00248 {
00249 LM_ERR("unsupported stale value \"%.*s\"\n",val.len,val.s);
00250 goto error;
00251 }
00252 break;
00253 default:
00254 break;
00255 }
00256 }
00257
00258
00259 if (auth->nonce.s==0 || auth->realm.s==0)
00260 {
00261 LM_ERR("realm or nonce missing\n");
00262 goto error;
00263 }
00264
00265 return 0;
00266 parse_error:
00267 LM_ERR("parse error in <%.*s> around %ld\n", body->len, body->s, (long)(p-body->s));
00268 error:
00269 return -1;
00270 }
00271
00272
00273 #define AUTHORIZATION_HDR_START "Authorization: Digest "
00274 #define AUTHORIZATION_HDR_START_LEN (sizeof(AUTHORIZATION_HDR_START)-1)
00275
00276 #define PROXY_AUTHORIZATION_HDR_START "Proxy-Authorization: Digest "
00277 #define PROXY_AUTHORIZATION_HDR_START_LEN \
00278 (sizeof(PROXY_AUTHORIZATION_HDR_START)-1)
00279
00280 #define USERNAME_FIELD_S "username=\""
00281 #define USERNAME_FIELD_LEN (sizeof(USERNAME_FIELD_S)-1)
00282 #define REALM_FIELD_S "realm=\""
00283 #define REALM_FIELD_LEN (sizeof(REALM_FIELD_S)-1)
00284 #define NONCE_FIELD_S "nonce=\""
00285 #define NONCE_FIELD_LEN (sizeof(NONCE_FIELD_S)-1)
00286 #define URI_FIELD_S "uri=\""
00287 #define URI_FIELD_LEN (sizeof(URI_FIELD_S)-1)
00288 #define OPAQUE_FIELD_S "opaque=\""
00289 #define OPAQUE_FIELD_LEN (sizeof(OPAQUE_FIELD_S)-1)
00290 #define RESPONSE_FIELD_S "response=\""
00291 #define RESPONSE_FIELD_LEN (sizeof(RESPONSE_FIELD_S)-1)
00292 #define ALGORITHM_FIELD_S "algorithm=MD5"
00293 #define ALGORITHM_FIELD_LEN (sizeof(ALGORITHM_FIELD_S)-1)
00294 #define FIELD_SEPARATOR_S "\", "
00295 #define FIELD_SEPARATOR_LEN (sizeof(FIELD_SEPARATOR_S)-1)
00296 #define FIELD_SEPARATOR_UQ_S ", "
00297 #define FIELD_SEPARATOR_UQ_LEN (sizeof(FIELD_SEPARATOR_UQ_S)-1)
00298
00299 #define QOP_FIELD_S "qop="
00300 #define QOP_FIELD_LEN (sizeof(QOP_FIELD_S)-1)
00301 #define NC_FIELD_S "nc="
00302 #define NC_FIELD_LEN (sizeof(NC_FIELD_S)-1)
00303 #define CNONCE_FIELD_S "cnonce=\""
00304 #define CNONCE_FIELD_LEN (sizeof(CNONCE_FIELD_S)-1)
00305
00306 #define add_string( _p, _s, _l) \
00307 do {\
00308 memcpy( _p, _s, _l);\
00309 _p += _l; \
00310 }while(0)
00311
00312
00313 str* build_authorization_hdr(int code, str *uri,
00314 struct uac_credential *crd, struct authenticate_body *auth,
00315 char *response)
00316 {
00317 static str hdr;
00318 char *p;
00319 int len;
00320 int response_len;
00321
00322 response_len = strlen(response);
00323
00324
00325 len = (code==401?
00326 AUTHORIZATION_HDR_START_LEN:PROXY_AUTHORIZATION_HDR_START_LEN) +
00327 USERNAME_FIELD_LEN + crd->user.len + FIELD_SEPARATOR_LEN +
00328 REALM_FIELD_LEN + crd->realm.len + FIELD_SEPARATOR_LEN +
00329 NONCE_FIELD_LEN + auth->nonce.len + FIELD_SEPARATOR_LEN +
00330 URI_FIELD_LEN + uri->len + FIELD_SEPARATOR_LEN +
00331 (auth->opaque.len?
00332 (OPAQUE_FIELD_LEN + auth->opaque.len + FIELD_SEPARATOR_LEN):0) +
00333 RESPONSE_FIELD_LEN + response_len + FIELD_SEPARATOR_LEN +
00334 ALGORITHM_FIELD_LEN + CRLF_LEN;
00335 if((auth->flags&QOP_AUTH) || (auth->flags&QOP_AUTH_INT))
00336 len += QOP_FIELD_LEN + 4 + FIELD_SEPARATOR_UQ_LEN +
00337 NC_FIELD_LEN + auth->nc->len + FIELD_SEPARATOR_UQ_LEN +
00338 CNONCE_FIELD_LEN + auth->cnonce->len + FIELD_SEPARATOR_LEN;
00339
00340 hdr.s = (char*)pkg_malloc( len + 1);
00341 if (hdr.s==0)
00342 {
00343 LM_ERR("no more pkg mem\n");
00344 goto error;
00345 }
00346
00347 p = hdr.s;
00348
00349 if (code==401)
00350 {
00351 add_string( p, AUTHORIZATION_HDR_START USERNAME_FIELD_S,
00352 AUTHORIZATION_HDR_START_LEN+USERNAME_FIELD_LEN);
00353 } else {
00354 add_string( p, PROXY_AUTHORIZATION_HDR_START USERNAME_FIELD_S,
00355 PROXY_AUTHORIZATION_HDR_START_LEN+USERNAME_FIELD_LEN);
00356 }
00357
00358 add_string( p, crd->user.s, crd->user.len);
00359
00360 add_string( p, FIELD_SEPARATOR_S REALM_FIELD_S,
00361 FIELD_SEPARATOR_LEN+REALM_FIELD_LEN);
00362 add_string( p, crd->realm.s, crd->realm.len);
00363
00364 add_string( p, FIELD_SEPARATOR_S NONCE_FIELD_S,
00365 FIELD_SEPARATOR_LEN+NONCE_FIELD_LEN);
00366 add_string( p, auth->nonce.s, auth->nonce.len);
00367
00368 add_string( p, FIELD_SEPARATOR_S URI_FIELD_S,
00369 FIELD_SEPARATOR_LEN+URI_FIELD_LEN);
00370 add_string( p, uri->s, uri->len);
00371
00372 if (auth->opaque.len )
00373 {
00374 add_string( p, FIELD_SEPARATOR_S OPAQUE_FIELD_S,
00375 FIELD_SEPARATOR_LEN+OPAQUE_FIELD_LEN);
00376 add_string( p, auth->opaque.s, auth->opaque.len);
00377 }
00378 if((auth->flags&QOP_AUTH) || (auth->flags&QOP_AUTH_INT))
00379 {
00380 add_string( p, FIELD_SEPARATOR_S QOP_FIELD_S,
00381 FIELD_SEPARATOR_LEN+QOP_FIELD_LEN);
00382 add_string( p, "auth", 4);
00383 add_string( p, FIELD_SEPARATOR_UQ_S NC_FIELD_S,
00384 FIELD_SEPARATOR_UQ_LEN+NC_FIELD_LEN);
00385 add_string( p, auth->nc->s, auth->nc->len);
00386 add_string( p, FIELD_SEPARATOR_UQ_S CNONCE_FIELD_S,
00387 FIELD_SEPARATOR_UQ_LEN+CNONCE_FIELD_LEN);
00388 add_string( p, auth->cnonce->s, auth->cnonce->len);
00389 }
00390
00391 add_string( p, FIELD_SEPARATOR_S RESPONSE_FIELD_S,
00392 FIELD_SEPARATOR_LEN+RESPONSE_FIELD_LEN);
00393 add_string( p, response, response_len);
00394
00395 add_string( p, FIELD_SEPARATOR_S ALGORITHM_FIELD_S CRLF,
00396 FIELD_SEPARATOR_LEN+ALGORITHM_FIELD_LEN+CRLF_LEN);
00397
00398 hdr.len = p - hdr.s;
00399
00400 if (hdr.len!=len)
00401 {
00402 LM_CRIT("BUG: bad buffer computation "
00403 "(%d<>%d)\n",len,hdr.len);
00404 pkg_free( hdr.s );
00405 goto error;
00406 }
00407
00408 LM_DBG("hdr is <%.*s>\n",
00409 hdr.len,hdr.s);
00410
00411 return &hdr;
00412 error:
00413 return 0;
00414 }
00415