4e4847d8552f8ca2966df6d3753bc5f6d8bbab14
[sip-router] / src / modules / auth_diameter / user_in.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
49 /* headers defined by this module */
50 #include "diameter_msg.h"
51 #include "auth_diameter.h"
52 #include "defs.h"
53 #include "tcp_comm.h"
54
55
56 /* Get To header field URI */
57 static inline int get_to_uri(struct sip_msg* m, str* u)
58 {
59      // check that the header field is there and is parsed
60         if (!m->to && ((parse_headers(m, HDR_TO_F, 0) == -1)|| (!m->to))) 
61         {
62                 LM_ERR("can't get To header field\n");
63                 return -1;
64         }
65         
66         u->s   = ((struct to_body*)m->to->parsed)->uri.s;
67         u->len = ((struct to_body*)m->to->parsed)->uri.len;
68         
69         return 0;
70 }
71
72
73 /* Get From header field URI */
74 static inline int get_from_uri(struct sip_msg* m, str* u)
75 {
76      // check that the header field is there and is parsed
77         if (parse_from_header(m) < 0) {
78                 LM_ERR("failed to parse From body\n");
79                 return -1;
80         }
81         
82         u->s   = ((struct to_body*)m->from->parsed)->uri.s;
83         u->len = ((struct to_body*)m->from->parsed)->uri.len;
84
85         return 0;
86 }
87
88 /* it checks if a user is member of a group */
89 int diameter_is_user_in(struct sip_msg* _m, char* _hf, char* _group)
90 {
91         str *grp, user_name, user, domain, uri;
92         dig_cred_t* cred = 0;
93         int hf_type;
94         struct hdr_field* h;
95         struct sip_uri puri;
96         AAAMessage *req;
97         AAA_AVP *avp; 
98         int ret;
99         unsigned int tmp;
100         char *p = NULL;
101
102         grp = (str*)_group; /* via fixup */
103
104         hf_type = (int)(long)_hf;
105
106         uri.s = 0;
107         uri.len = 0;
108
109         /* extract the uri according with the _hf parameter */
110         switch(hf_type) 
111         {
112                 case 1: /* Request-URI */
113                         uri = *(GET_RURI(_m));
114                 break;
115
116                 case 2: /* To */
117                         if (get_to_uri(_m, &uri) < 0) 
118                         {
119                                 LM_ERR("failed to extract To\n");
120                                 return -2;
121                         }
122                         break;
123
124                 case 3: /* From */
125                         if (get_from_uri(_m, &uri) < 0) 
126                         {
127                                 LM_ERR("failed to extract From URI\n");
128                                 return -3;
129                         }
130                         break;
131
132                 case 4: /* Credentials */
133                         get_authorized_cred(_m->authorization, &h);
134                         if (!h)         
135                         {
136                                 get_authorized_cred(_m->proxy_auth, &h);
137                                 if (!h) 
138                                 {
139                                         LM_ERR("no authorized credentials found "
140                                                         "(error in scripts)\n");
141                                         return -4;
142                                 }
143                         }
144                         cred = &((auth_body_t*)(h->parsed))->digest;
145                         break;
146         }
147
148         if (hf_type != 4) 
149         {
150                 if (parse_uri(uri.s, uri.len, &puri) < 0) 
151                 {
152                         LM_ERR("failed to parse URI\n");
153                         return -5;
154                 }
155                 user = puri.user;
156                 domain = puri.host;
157         } 
158         else
159         {
160                 user = cred->username.user;
161                 domain = cred->realm;
162         }
163         
164         /* user@domain mode */
165         if (use_domain)
166         {
167                 user_name.s = 0;
168                 user_name.len = user.len + domain.len;
169                 if(user_name.len>0)
170                 {
171                         user_name.len++;
172                         p = (char*)pkg_malloc(user_name.len);
173                         if (!p)
174                         {
175                                 LM_ERR("no pkg memory left\n");
176                                 return -6;
177                         }
178                         user_name.s = p;
179                 
180                         memcpy(user_name.s, user.s, user.len);
181                         if(user.len>0)
182                         {
183                                 user_name.s[user.len] = '@';
184                                 memcpy(user_name.s + user.len + 1, domain.s, domain.len);
185                         }
186                         else
187                                 memcpy(user_name.s, domain.s, domain.len);
188                 }
189         } 
190         else 
191                 user_name = user;
192         
193         
194         if ( (req=AAAInMessage(AA_REQUEST, AAA_APP_NASREQ))==NULL)
195         {
196                 LM_ERR("can't create new AAA message!\n");
197                 if(p) pkg_free(p);
198                 return -1;
199         }
200         
201         /* Username AVP */
202         if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s,
203                                 user_name.len, AVP_DUPLICATE_DATA)) == 0)
204         {
205                 LM_ERR("no more pkg memory!\n");
206                 goto error;
207         }
208         if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
209         {
210                 LM_ERR("avp not added \n");
211                 goto error1;
212         }
213
214         /* Usergroup AVP */
215         if( (avp=AAACreateAVP(AVP_User_Group, 0, 0, grp->s,
216                                 grp->len, AVP_DUPLICATE_DATA)) == 0)
217         {
218                 LM_ERR("no more pkg memory!\n");
219                 goto error;
220         }
221         if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
222         {
223                 LM_ERR("avp not added \n");
224                 goto error1;
225         }
226
227         /* SIP_MSGID AVP */
228         LM_DBG("******* m_id=%d\n", _m->id);
229         tmp = _m->id;
230         if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&tmp), 
231                                 sizeof(tmp), AVP_DUPLICATE_DATA)) == 0)
232         {
233                 LM_ERR("no more pkg memory!\n");
234                 goto error;
235         }
236         if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
237         {
238                 LM_ERR("avp not added \n");
239                 goto error1;
240         }
241
242         
243         /* ServiceType AVP */
244         if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_GROUP_CHECK, 
245                                 SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0)
246         {
247                 LM_ERR("no more pkg memory!\n");
248                 goto error;
249         }
250         if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
251         {
252                 LM_ERR("avp not added \n");
253                 goto error1;
254         }
255         
256
257         /* Destination-Realm AVP */
258         uri = *(GET_RURI(_m));
259         parse_uri(uri.s, uri.len, &puri);
260         if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s,
261                                                 puri.host.len, AVP_DUPLICATE_DATA)) == 0)
262         {
263                 LM_ERR("no more pkg memory!\n");
264                 goto error;
265         }
266         
267         if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
268         {
269                 LM_ERR("avp not added \n");
270                 goto error1;
271         }
272         
273 #ifdef DEBUG
274         AAAPrintMessage(req);
275 #endif
276
277         /* build a AAA message buffer */
278         if(AAABuildMsgBuffer(req) != AAA_ERR_SUCCESS)
279         {
280                 LM_ERR("message buffer not created\n");
281                 goto error;
282         }
283
284         if(sockfd==AAA_NO_CONNECTION)
285         {
286                 sockfd = init_mytcp(diameter_client_host, diameter_client_port);
287                 if(sockfd==AAA_NO_CONNECTION)
288                 {
289                         LM_ERR("failed to reconnect to Diameter client\n");
290                         goto error;
291                 }
292         }
293
294         ret =tcp_send_recv(sockfd, req->buf.s, req->buf.len, rb, _m->id);
295
296         if(ret == AAA_CONN_CLOSED)
297         {
298                 LM_NOTICE("connection to Diameter client closed."
299                                 "It will be reopened by the next request\n");
300                 close(sockfd);
301                 sockfd = AAA_NO_CONNECTION;
302                 goto error;
303         }
304         if(ret != AAA_USER_IN_GROUP)
305         {
306                 LM_ERR("message sending to the DIAMETER backend authorization server"
307                                 "failed or user is not in group\n");
308                 goto error;
309         }
310         
311         AAAFreeMessage(&req);
312         return 1;
313
314 error1:
315         AAAFreeAVP(&avp);
316 error:
317         AAAFreeMessage(&req);
318         return -1;
319
320 }
321