auth_diameter: avoid passing large structs as params and better error handling
[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         /* ServiceType AVP */
243         if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_GROUP_CHECK, 
244                                 SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0)
245         {
246                 LM_ERR("no more pkg memory!\n");
247                 goto error;
248         }
249         if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
250         {
251                 LM_ERR("avp not added \n");
252                 goto error1;
253         }
254
255         /* Destination-Realm AVP */
256         uri = *(GET_RURI(_m));
257         if(parse_uri(uri.s, uri.len, &puri)<0) {
258                 LM_ERR("failed to parse uri\n");
259                 goto error;
260         }
261         if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s,
262                                                 puri.host.len, AVP_DUPLICATE_DATA)) == 0)
263         {
264                 LM_ERR("no more pkg memory!\n");
265                 goto error;
266         }
267
268         if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
269         {
270                 LM_ERR("avp not added \n");
271                 goto error1;
272         }
273
274 #ifdef DEBUG
275         AAAPrintMessage(req);
276 #endif
277
278         /* build a AAA message buffer */
279         if(AAABuildMsgBuffer(req) != AAA_ERR_SUCCESS)
280         {
281                 LM_ERR("message buffer not created\n");
282                 goto error;
283         }
284
285         if(sockfd==AAA_NO_CONNECTION)
286         {
287                 sockfd = init_mytcp(diameter_client_host, diameter_client_port);
288                 if(sockfd==AAA_NO_CONNECTION)
289                 {
290                         LM_ERR("failed to reconnect to Diameter client\n");
291                         goto error;
292                 }
293         }
294
295         ret =tcp_send_recv(sockfd, req->buf.s, req->buf.len, rb, _m->id);
296
297         if(ret == AAA_CONN_CLOSED)
298         {
299                 LM_NOTICE("connection to Diameter client closed."
300                                 "It will be reopened by the next request\n");
301                 close(sockfd);
302                 sockfd = AAA_NO_CONNECTION;
303                 goto error;
304         }
305         if(ret != AAA_USER_IN_GROUP)
306         {
307                 LM_ERR("message sending to the DIAMETER backend authorization server"
308                                 "failed or user is not in group\n");
309                 goto error;
310         }
311         
312         AAAFreeMessage(&req);
313         return 1;
314
315 error1:
316         AAAFreeAVP(&avp);
317 error:
318         AAAFreeMessage(&req);
319         return -1;
320
321 }