996d122f48a0f812f00adcb2023570d7757586fe
[sip-router] / src / modules / auth_diameter / authorize.c
1 /*
2  * Digest Authentication - Diameter support
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *`
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  * 
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License 
19  * along with this program; if not, write to the Free Software 
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <netdb.h> 
31 #include <string.h>
32
33 /* memory management */
34 #include "../../core/mem/mem.h"
35 #include "../../core/mem/shm_mem.h"
36
37 /* printing messages, dealing with strings and other utils */
38 #include "../../core/dprint.h"
39 #include "../../core/str.h"
40 #include "../../core/ut.h"
41
42 /* digest parser headers */
43 #include "../../core/parser/digest/digest.h"
44 #include "../../core/parser/parse_uri.h"
45 #include "../../core/parser/parse_from.h"
46 #include "../../core/parser/parse_to.h"
47
48 /* necessary when dealing with lumps */
49 #include "../../core/data_lump_rpl.h"
50
51 /* headers defined by this module */
52 #include "diameter_msg.h"
53 #include "auth_diameter.h"
54 #include "defs.h"
55 #include "authorize.h"
56 #include "tcp_comm.h"
57
58 static str dia_401_err = str_init(MESSAGE_401);
59 static str dia_403_err = str_init("Forbidden");
60 static str dia_407_err = str_init(MESSAGE_407);
61 static str dia_400_err = str_init(MESSAGE_400);
62 static str dia_500_err = str_init(MESSAGE_500);
63
64
65 /* Extract URI depending on the request from To or From header */
66 int get_uri(struct sip_msg* m, str** uri)
67 {
68         if ((REQ_LINE(m).method.len == 8) && 
69                                         (memcmp(REQ_LINE(m).method.s, "REGISTER", 8) == 0)) 
70         {       
71                 /* REGISTER */
72                 if (!m->to && ((parse_headers(m, HDR_TO_F, 0) == -1)|| (!m->to))) 
73                 {
74                         LM_ERR("the To header field was not found or malformed\n");
75                         
76                         /* it was a REGISTER and an error appeared when parsing TO header*/
77                         return -1;
78                 }
79                 *uri = &(get_to(m)->uri);
80         } 
81         else 
82         {
83                 if (parse_from_header(m)<0)
84                 {
85                         LM_ERR("failed to parse FROM header\n");
86
87                         /* an error appeared when parsing FROM header */
88                         return -1;
89                 }
90                 *uri = &(get_from(m)->uri);
91         }
92
93     /* success */
94         return 0;
95 }
96
97
98 /* Return parsed To or From host part of the parsed uri (that is realm) */
99 int get_realm(struct sip_msg* m, int hftype, struct sip_uri* u)
100 {
101         str uri;
102
103         /* extracting the uri */
104         if ((REQ_LINE(m).method.len==8)
105                                         && !memcmp(REQ_LINE(m).method.s, "REGISTER", 8) 
106                                         && (hftype == HDR_AUTHORIZATION_T) ) 
107         { 
108                 /* REGISTER */
109                 if (!m->to && ((parse_headers(m, HDR_TO_F, 0) == -1) || (!m->to))) 
110                 {
111                         LM_ERR("failed to parse TO header\n");
112                         /* signal the error */
113                         return -1;
114                 }
115                 
116             /* Body of To header field is parsed automatically */
117                 uri = get_to(m)->uri; 
118         } 
119         else 
120         {
121                 if (parse_from_header(m)<0) 
122                 {
123                         LM_ERR("failed to parse FROM header\n");
124                         /* signal the error */
125                         return -1;
126                 }
127
128                 uri = get_from(m)->uri;
129         }
130         
131         /* parsing the uri */
132         if (parse_uri(uri.s, uri.len, u) < 0) 
133         {
134                 LM_ERR("failed to parse URI\n");
135                 return -1;
136         }
137         
138         /* everything was OK */
139         return 0;
140 }
141
142
143 auth_diam_result_t diam_pre_auth(struct sip_msg* _m, str* _realm, int _hftype, 
144                                                                                                         struct hdr_field** _h)
145 {
146         int ret;
147         struct sip_uri uri;
148         str realm;
149
150         if ((_m->REQ_METHOD == METHOD_ACK) ||  (_m->REQ_METHOD == METHOD_CANCEL))
151                 return AUTHORIZED;
152
153         /* if no realm supplied, find out now */
154         if (_realm==0 || _realm->len == 0) 
155         {
156                 if (get_realm(_m, _hftype, &uri) < 0) 
157                 {
158                         LM_ERR("failed to extract realm\n");
159                         if (send_resp(_m, 400, &dia_400_err, 0, 0) == -1) 
160                         {
161                                 LM_ERR("failed to send 400 reply\n");
162                         }
163                         return ERROR;
164                 }
165                 realm = uri.host;
166         } else {
167                 realm = *_realm;
168         }
169
170         ret = find_credentials(_m, &realm, _hftype, _h);
171         if (ret < 0) 
172         {
173                 LM_ERR("credentials not found\n");
174                 if (send_resp(_m, (ret == -2) ? 500 : 400, 
175                               (ret == -2) ? &dia_500_err : &dia_400_err, 0, 0) == -1) 
176                 {
177                         LM_ERR("failed to send 400 reply\n");
178                 }
179                 return ERROR;
180         } 
181         else 
182                 if (ret > 0) 
183                 {
184                         LM_ERR("credentials with given realm not found\n");
185                         return NO_CREDENTIALS;
186                 }
187         
188
189         return DO_AUTHORIZATION;
190 }
191
192
193 /* Authorize digest credentials */
194 int authorize(struct sip_msg* msg, pv_elem_t* realm, int hftype)
195 {
196         auth_diam_result_t ret;
197         struct hdr_field* h;
198         auth_body_t* cred = NULL;
199         str* uri;
200         struct sip_uri puri;
201         str  domain;
202
203         if (realm) {
204                 if (pv_printf_s(msg, realm, &domain)!=0) {
205                         LM_ERR("pv_printf_s failed\n");
206                         return AUTH_ERROR;
207                 }
208         } else {
209                 domain.len = 0;
210                 domain.s = 0;
211         }
212
213         /* see what is to do after a first look at the message */
214         ret = diam_pre_auth(msg, &domain, hftype, &h);
215
216         switch(ret) 
217         {
218                 case NO_CREDENTIALS:   cred = NULL;
219                                                            break;
220
221                 case DO_AUTHORIZATION: cred = (auth_body_t*)h->parsed;
222                                                            break;
223                 default:               return ret;
224         }
225
226         if (get_uri(msg, &uri) < 0) 
227         {
228                 LM_ERR("From/To URI not found\n");
229                 return AUTH_ERROR;
230         }
231         
232         if (parse_uri(uri->s, uri->len, &puri) < 0) 
233         {
234                 LM_ERR("failed to parse From/To URI\n");
235                 return AUTH_ERROR;
236         }
237 //      user.s = (char *)pkg_malloc(puri.user.len);
238 //      un_escape(&(puri.user), &user);
239         
240         /* parse the ruri, if not yet */
241         if(msg->parsed_uri_ok==0 && parse_sip_msg_uri(msg)<0)
242         {
243                 LM_ERR("failed to parse the Request-URI\n");
244                 return AUTH_ERROR;
245         }
246         
247         /* preliminary check */
248         if(cred)
249         {
250                 if (puri.host.len != cred->digest.realm.len) 
251                 {
252                         LM_DBG("credentials realm and URI host do not match\n");  
253                         return AUTH_ERROR;
254                 }
255         
256                 if (strncasecmp(puri.host.s, cred->digest.realm.s, puri.host.len) != 0) 
257                 {
258                         LM_DBG("credentials realm and URI host do not match\n");
259                         return AUTH_ERROR;
260                 }
261         }
262         
263         if( diameter_authorize(cred?h:NULL, &msg->first_line.u.request.method,
264                                         puri, msg->parsed_uri, msg->id, rb) != 1)
265         {
266                 send_resp(msg, 500, &dia_500_err, NULL, 0);
267                 return AUTH_ERROR;
268         }
269         
270         if( srv_response(msg, rb, hftype) != 1 )
271                 return AUTH_ERROR;
272
273         mark_authorized_cred(msg, h);
274
275         return AUTHORIZED;
276 }
277
278
279
280 /*
281  * This function creates and submits diameter authentication request as per
282  * draft-srinivas-aaa-basic-digest-00.txt. 
283  * Service type of the request is Authenticate-Only.
284  * Returns:
285  *               1 - success
286  *              -1 - error
287  *                      
288  */
289 int diameter_authorize(struct hdr_field* hdr, str* p_method, struct sip_uri uri,
290                                                 struct sip_uri ruri, unsigned int m_id, rd_buf_t* rb)
291 {
292         str user_name;
293         AAAMessage *req;
294         AAA_AVP *avp, *position; 
295         int name_flag, port_flag;
296         dig_cred_t* cred;
297         unsigned int tmp;
298
299         if ( !p_method )
300         {
301                 LM_ERR("invalid parameter value\n");
302                 return -1;
303         }
304
305         if ( (req=AAAInMessage(AA_REQUEST, AAA_APP_NASREQ))==NULL)
306                 return -1;
307
308         if(hdr && hdr->parsed)
309                 cred = &(((auth_body_t*)hdr->parsed)->digest);
310         else
311                 cred = NULL;
312                         
313         if(!cred)
314         {
315                 /* Username AVP */
316                 user_name.s = 0;
317                 user_name.len = uri.user.len + uri.host.len;
318                 if(user_name.len>0)
319                 {
320                         user_name.len += 2;
321                         user_name.s = (char*)ad_malloc(user_name.len*sizeof(char));
322                         memset(user_name.s, 0, user_name.len);
323
324                         memcpy(user_name.s, uri.user.s, uri.user.len);
325                         if(uri.user.len>0)
326                         {
327                                 memcpy(user_name.s+uri.user.len, "@", 1);
328                                 memcpy(user_name.s+uri.user.len+1, uri.host.s, uri.host.len);
329                         }
330                         else
331                                 memcpy(user_name.s, uri.host.s, uri.host.len);
332                 }
333
334                 if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s, 
335                                                         user_name.len, AVP_FREE_DATA)) == 0)
336                 {
337                         LM_ERR("no more pkg memory left!\n");
338                         if(user_name.len>0)
339                                 pkg_free(user_name.s);
340                         goto error;
341                 }
342                 if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
343                 {
344                         LM_ERR("avp not added \n");
345                         goto error1;
346                 }
347         }
348         else /* it is a SIP message with credentials */
349         {
350                 /* Add Username AVP */
351                 if (cred->username.domain.len>0) 
352                 {
353                         if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, cred->username.whole.s,
354                                                         cred->username.whole.len, AVP_DUPLICATE_DATA)) == 0)
355                         {
356                                 LM_ERR("no more pkg memory left!\n");
357                                 goto error;
358                         }
359
360                         if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
361                         {
362                                 LM_ERR("avp not added \n");
363                                 goto error1;
364                         }
365                 }
366                 else 
367                 {
368                         user_name.s = 0;
369                         user_name.len = cred->username.user.len + cred->realm.len;
370                         if(user_name.len>0)
371                         {
372                                 user_name.s = ad_malloc(user_name.len);
373                                 if (!user_name.s) 
374                                 {
375                                         LM_ERR(" no more pkg memory left\n");
376                                         goto error;
377                                 }
378                                 memcpy(user_name.s, cred->username.whole.s, 
379                                                                         cred->username.whole.len);
380                                 if(cred->username.whole.len>0)
381                                 {
382                                         user_name.s[cred->username.whole.len] = '@';
383                                         memcpy(user_name.s + cred->username.whole.len + 1, 
384                                                         cred->realm.s, cred->realm.len);
385                                 }
386                                 else
387                                         memcpy(user_name.s,     cred->realm.s, cred->realm.len);
388                         }
389
390                         if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s, 
391                                                         user_name.len, AVP_FREE_DATA)) == 0)
392                         {
393                                 LM_ERR(" no more pkg memory left!\n");
394                                 if(user_name.len>0)
395                                         pkg_free(user_name.s);
396                                 goto error;
397                         }
398
399                         if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
400                         {
401                                 LM_ERR(" avp not added \n");
402                                 goto error1;
403                         }
404                 }
405         }
406
407         /* SIP_MSGID AVP */
408         LM_DBG("******* m_id=%d\n", m_id);
409         tmp = m_id;
410         if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&tmp), 
411                                 sizeof(m_id), AVP_DUPLICATE_DATA)) == 0)
412         {
413                 LM_ERR(" no more pkg memory left!\n");
414                 goto error;
415         }
416         if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
417         {
418                 LM_ERR(" avp not added \n");
419                 goto error1;
420         }
421
422         
423         
424         /* SIP Service AVP */
425         if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_AUTHENTICATION, 
426                                 SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0)
427         {
428                 LM_ERR(" no more pkg memory left!\n");
429                 goto error;
430         }
431         if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
432         {
433                 LM_ERR(" avp not added \n");
434                 goto error1;
435         }
436                 
437         /* Destination-Realm AVP */
438         if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, uri.host.s,
439                                                 uri.host.len, AVP_DUPLICATE_DATA)) == 0)
440         {
441                 LM_ERR(" no more pkg memory left!\n");
442                 goto error;
443         }
444
445 #ifdef DEBUG    
446         LM_DBG("Destination Realm: %.*s\n", uri.host.len, uri.host.s);  
447 #endif
448
449         if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
450         {
451                 LM_ERR(" avp not added \n");
452                 goto error1;
453         }
454         
455         /* Resource AVP */
456         user_name.len = ruri.user.len + ruri.host.len + ruri.port.len + 2;
457         user_name.s = (char*)ad_malloc(user_name.len*sizeof(char));
458         memset(user_name.s, 0, user_name.len);
459         memcpy(user_name.s, ruri.user.s, ruri.user.len);
460
461         name_flag= 0;
462         if(ruri.user.s)
463         {               
464                 name_flag = 1;
465                 memcpy(user_name.s+ruri.user.len, "@", 1);
466         }       
467
468         memcpy(user_name.s+ruri.user.len+name_flag, ruri.host.s, ruri.host.len);
469
470         port_flag=0;
471         if(ruri.port.s)
472         {
473                 port_flag = 1;  
474                 memcpy(user_name.s+ruri.user.len+ruri.host.len+1, ":", 1);
475                 memcpy(user_name.s+ruri.user.len+ruri.host.len+name_flag+port_flag, 
476                                         ruri.port.s, ruri.port.len);
477         }
478 #ifdef DEBUG
479         LM_DBG(": AVP_Resource=%.*s\n", user_name.len, user_name.s);
480 #endif
481
482         if( (avp=AAACreateAVP(AVP_Resource, 0, 0, user_name.s,
483                                                 user_name.len, AVP_FREE_DATA)) == 0)
484         {
485                 LM_ERR(" no more pkg memory left!\n");
486                 if(user_name.s)
487                         pkg_free(user_name.s);
488                 goto error;
489         }
490         if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
491         {
492                 LM_ERR(" avp not added \n");
493                 goto error1;
494         }
495
496         if(cred) /* it is a SIP message with credentials */
497         {
498                 /* Response AVP */
499                 if( (avp=AAACreateAVP(AVP_Response, 0, 0, hdr->body.s,
500                                                 hdr->body.len, AVP_DUPLICATE_DATA)) == 0)
501                 {
502                         LM_ERR(" no more pkg memory left!\n");
503                         goto error;
504                 }
505                 
506                 position = AAAGetLastAVP(&(req->avpList));
507                 if( AAAAddAVPToMessage(req, avp, position)!= AAA_ERR_SUCCESS)
508                                 
509                 {
510                         LM_ERR(" avp not added \n");
511                         goto error1;
512                 }
513
514                 /* Method AVP */
515                 if( (avp=AAACreateAVP(AVP_Method, 0, 0, p_method->s,
516                                                 p_method->len, AVP_DUPLICATE_DATA)) == 0)
517                 {
518                         LM_ERR(" no more pkg memory left!\n");
519                         goto error;
520                 }
521                 
522                 position = AAAGetLastAVP(&(req->avpList));
523                 if( AAAAddAVPToMessage(req, avp, position)!= AAA_ERR_SUCCESS)
524                                 
525                 {
526                         LM_ERR(" avp not added \n");
527                         goto error1;
528                 }
529
530         
531         }                       
532 #ifdef DEBUG
533         AAAPrintMessage(req);
534 #endif
535
536         /* build a AAA message buffer */
537         if(AAABuildMsgBuffer(req) != AAA_ERR_SUCCESS)
538         {
539                 LM_ERR(" message buffer not created\n");
540                 goto error;
541         }
542         
543         if(sockfd==AAA_NO_CONNECTION)
544         {
545                 sockfd = init_mytcp(diameter_client_host, diameter_client_port);
546                 if(sockfd==AAA_NO_CONNECTION)
547                 {
548                         LM_ERR(" failed to reconnect to Diameter client\n");
549                         goto error;
550                 }
551         }
552
553         /* send the message to the DIAMETER CLIENT */
554         switch( tcp_send_recv(sockfd, req->buf.s, req->buf.len, rb, m_id) )
555         {
556                 case AAA_ERROR: /* a transmission error occurred */
557                         LM_ERR(" message sending to the" 
558                                         " DIAMETER backend authorization server failed\n");
559                         goto error;
560         
561                 case AAA_CONN_CLOSED:
562                         LM_NOTICE("connection to Diameter"
563                                         " client closed.It will be reopened by the next request\n");
564                         close(sockfd);
565                         sockfd = AAA_NO_CONNECTION;
566                         goto error;
567
568                 case AAA_TIMEOUT:
569                         LM_NOTICE("no response received\n");
570                         close(sockfd);
571                         sockfd = AAA_NO_CONNECTION;
572                         goto error;
573         }
574
575         AAAFreeMessage(&req);
576         return 1;
577
578 error1:
579         AAAFreeAVP(&avp);
580 error:
581         AAAFreeMessage(&req);
582         return -1;
583 }
584
585 /* give the appropriate response to the SER client */
586 int srv_response(struct sip_msg* msg, rd_buf_t * rb, int hftype)
587 {
588         int auth_hf_len=0, ret=0;
589         char* auth_hf;
590
591         switch(rb->ret_code)
592         {
593                 case AAA_AUTHORIZED:
594                         return 1;
595                         
596                 case AAA_NOT_AUTHORIZED:
597                         send_resp(msg, 403, &dia_403_err, NULL, 0);
598                         return -1;
599
600                 case AAA_SRVERR:
601                         send_resp(msg, 500, &dia_500_err, NULL, 0);
602                         return -1;
603                                 
604                 case AAA_CHALENGE:
605                         if(hftype==HDR_AUTHORIZATION_T) /* SIP server */
606                         {
607                                 auth_hf_len = WWW_AUTH_CHALLENGE_LEN+rb->chall_len;
608                                 auth_hf = (char*)ad_malloc(auth_hf_len*(sizeof(char)));
609                                 memset(auth_hf, 0, auth_hf_len);
610                                 memcpy(auth_hf,WWW_AUTH_CHALLENGE, WWW_AUTH_CHALLENGE_LEN);
611                                 memcpy(auth_hf+WWW_AUTH_CHALLENGE_LEN, rb->chall,
612                                         rb->chall_len);
613                 
614                                 ret = send_resp(msg, 401, &dia_401_err, auth_hf, auth_hf_len);
615
616                         }
617                         else    /* Proxy Server */
618                         {
619                                 auth_hf_len = PROXY_AUTH_CHALLENGE_LEN+rb->chall_len;
620                                 auth_hf = (char*)ad_malloc(auth_hf_len*(sizeof(char)));
621                                 memset(auth_hf, 0, auth_hf_len);
622                                 memcpy(auth_hf, PROXY_AUTH_CHALLENGE, PROXY_AUTH_CHALLENGE_LEN);
623                                 memcpy(auth_hf + PROXY_AUTH_CHALLENGE_LEN, rb->chall, 
624                                                 rb->chall_len);
625                                 ret = send_resp(msg, 407, &dia_407_err, auth_hf, auth_hf_len);
626                         }
627
628                         if (auth_hf) pkg_free(auth_hf);
629         
630                         if (ret == -1) 
631                         {
632                                 LM_ERR("failed to send challenge to the client of SER\n");
633                                 return -1;
634                         }
635                         return -1;
636         }
637         
638         // never reach this 
639         return -1;              
640 }
641
642
643 /*
644  * Create a response with given code and reason phrase
645  * Optionally add new headers specified in _hdr
646  */
647 int send_resp(struct sip_msg* m, int code, str* reason,
648                                         char* hdr, int hdr_len)
649 {
650         /* Add new headers if there are any */
651         if ((hdr) && (hdr_len)) {
652                 if (add_lump_rpl( m, hdr, hdr_len, LUMP_RPL_HDR)==0) {
653                         LM_ERR("unable to append hdr\n");
654                         return -1;
655                 }
656         }
657
658         return slb.freply(m, code, reason);
659 }
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676