blob: f87ceb6ac0a36becae5a82c603dd9e6607322531 [file] [log] [blame]
Brian Waters13d96012017-12-08 16:53:31 -06001/*********************************************************************************************************
2* Software License Agreement (BSD License) *
3* Author: Alexandre Westfahl <awestfahl@freediameter.net> *
4* *
5* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. *
6* *
7* All rights reserved. *
8* *
9* Redistribution and use of this software in source and binary forms, with or without modification, are *
10* permitted provided that the following conditions are met: *
11* *
12* * Redistributions of source code must retain the above *
13* copyright notice, this list of conditions and the *
14* following disclaimer. *
15* *
16* * Redistributions in binary form must reproduce the above *
17* copyright notice, this list of conditions and the *
18* following disclaimer in the documentation and/or other *
19* materials provided with the distribution. *
20* *
21* * Neither the name of the Teraoka Laboratory nor the *
22* names of its contributors may be used to endorse or *
23* promote products derived from this software without *
24* specific prior written permission of Teraoka Laboratory *
25* *
26* *
27* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
28* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
29* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
30* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
31* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
32* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
33* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
34* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
35*********************************************************************************************************/
36#include "app_sip.h"
37
38
39int app_sip_UAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
40{
41 TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
42
43 struct msg *ans, *qry;
44 struct avp *avp, *groupedavp=NULL;
45 struct avp_hdr *avphdr, *sipaorhdr, *visitednethdr, *usernamehdr;
46 union avp_value value;
47 int ret=0, hascap=0;
48
49 //Result_Code to return in the answer
50 char result[55];
51
52 if (msg == NULL)
53 return EINVAL;
54
55
56 // Create answer header
57 qry = *msg;
58 CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
59 ans = *msg;
60
61 //Add the Auth-Application-Id
62 {
63 CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
64 value.i32 = 6;
65 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
66 CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
67 }
68 // Add the Auth-Session-State AVP
69 {
70
71 CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
72 CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) );
73
74 CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
75 CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
76 CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
77 }
78
79 //Retrieve SIP-AOR
80 {
81 CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) );
82 CHECK_FCT( fd_msg_avp_hdr( avp, &sipaorhdr ) );
83 }
84
85 //We check if we have a User-Name AVP
86 {
87 CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.User_Name, &avp) );
88 if(avp!=NULL)
89 {
90 CHECK_FCT( fd_msg_avp_hdr( avp, &usernamehdr ) );
91
92 ret=get_password(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, NULL);
93
94
95 if(ret==1)
96 {//not found
97 strcpy(result,"DIAMETER_ERROR_USER_UNKNOWN");
98 goto out;
99 }
100 else if(ret==2)
101 {//error
102 //We couldn't make the request, we must stop process!
103 strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
104 goto out;
105 }
106 else if(ret==0)
107 {//found
108
109 //We must check that this user can use this SIP-AOR
110 ret=check_sipaor(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, (const char *)sipaorhdr->avp_value->os.data,sipaorhdr->avp_value->os.len);
111
112 if(ret==0)
113 {
114 //The SIP-AOR and Username are ok!
115 }
116 else if(ret==1)
117 {//not found
118 strcpy(result,"DIAMETER_ERROR_IDENTITIES_DONT_MATCH");
119 goto out;
120 }
121 else
122 {//error
123 //We couldn't make the request, we must stop process!
124 strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
125 goto out;
126 }
127 }
128 }
129 }
130
131 //We check if we have a SIP-Visited-Network-Id AVP
132 {
133 CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Visited_Network_Id, &avp) );
134
135 if(avp!=NULL)
136 {
137 CHECK_FCT( fd_msg_avp_hdr( avp, &visitednethdr ) );
138 }
139 else
140 visitednethdr=NULL;
141 }
142
143 //We check if we have a SIP_User_Authorization_Type
144 {
145 int auth_type;
146
147 CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_User_Authorization_Type, &avp) );
148
149 if(avp!=NULL)
150 {
151 CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) );
152 auth_type=avphdr->avp_value->i32;
153
154 if(auth_type==0 || auth_type==2)
155 {
156 if(visitednethdr!=NULL)
157 {
158 /*
159 If there is a SIP-Visited-Network-Id AVP in the Diameter UAR message,
160 and the SIP-User-Authorization-Type AVP value received in the
161 Diameter UAR message is set to REGISTRATION or REGISTRATION&
162 CAPABILITIES, then the Diameter server SHOULD verify whether the user
163 is allowed to roam into the network specified in the
164 SIP-Visited-Network-Id AVP in the Diameter UAR message. If the user
165 is not allowed to roam into that network, the Diameter AAA server
166 MUST set the Result-Code AVP value in the Diameter UAA message to
167 DIAMETER_ERROR_ROAMING_NOT_ALLOWED.
168 */
169 ret=allow_roaming(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, (const char *)visitednethdr->avp_value->os.data,visitednethdr->avp_value->os.len);
170
171 if(ret==0)
172 {
173 //This user can come in this network
174 }
175 else if(ret==1)
176 {
177 strcpy(result,"DIAMETER_ERROR_ROAMING_NOT_ALLOWED");
178 goto out;
179 }
180 else
181 {
182 strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
183 goto out;
184 }
185
186 }
187 /*
188 If the SIP-User-Authorization-Type AVP value received in the Diameter
189 UAR message is set to REGISTRATION or REGISTRATION&CAPABILITIES, then
190 the Diameter server SHOULD verify whether the SIP-AOR AVP value is
191 authorized to register in the Home Realm. Where the SIP AOR is not
192 authorized to register in the Home Realm, the Diameter server MUST
193 set the Result-Code AVP to DIAMETER_AUTHORIZATION_REJECTED and send
194 it in a Diameter UAA message.
195 */
196 ret=exist_username(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len);
197 if(ret==0)
198 {
199 //The SIP_AOR exists in this realm
200 }
201 else if(ret==1)
202 {
203 strcpy(result,"DIAMETER_AUTHORIZATION_REJECTED");
204 goto out;
205 }
206 else
207 {
208 strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
209 goto out;
210 }
211 }
212 }
213 else
214 auth_type=0; //Registration only (default value if absent)
215
216
217 //Let's look for the SIP_Server_URI'
218 unsigned char *sipserver_uri;
219 size_t sipserverurilen;
220
221 ret=get_sipserver_uri(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len, &sipserver_uri, &sipserverurilen);
222
223 if(ret==0)
224 {//We know a SIP Server so we must provide it
225 //We only add this AVP when we have registration or deregistration
226 if(auth_type==0 ||auth_type==1)
227 {
228 CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_URI, 0, &avp ) );
229 value.os.data=sipserver_uri;
230 value.os.len=sipserverurilen;
231 CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
232 CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
233 }
234 }
235 else if(ret==1)
236 {
237 sipserver_uri=NULL;
238 sipserverurilen=0;
239
240 }
241 else
242 {
243 strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
244 goto out;
245 }
246
247 //If we have a REGISTRATION or REGISTRATION & CAPABILITIES
248 if(auth_type==0 ||auth_type==2)
249 {
250 //Adding SIP-Server-Capabilities
251 CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_Capabilities, 0, &groupedavp ) );
252
253 ret=get_sipserver_cap(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len,&groupedavp);
254
255 if(ret==0)
256 {
257 CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, groupedavp) );
258 hascap=1;
259 }
260 else if(ret==1)
261 {
262
263 hascap=0;
264 }
265 else
266 {
267 CHECK_FCT( fd_msg_free( groupedavp ) );
268 strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
269 goto out;
270 }
271 }
272
273
274
275 if(auth_type==0)
276 {//Registration
277
278 if(sipserver_uri==NULL)
279 {
280 strcpy(result,"DIAMETER_FIRST_REGISTRATION");
281 }
282 else
283 {
284 if(hascap==1)
285 {
286 strcpy(result,"DIAMETER_SERVER_SELECTION");
287 }
288 else
289 {
290 //We free the Capabilities AVP because we didn't found any'
291 if(groupedavp!=NULL)
292 CHECK_FCT( fd_msg_free( groupedavp ) );
293 strcpy(result,"DIAMETER_SUBSEQUENT_REGISTRATION");
294 }
295 }
296 }
297 else if(auth_type==2)
298 {//Registration & Capabilities
299 //We let the groupedavp in the message even if there is no capabilities
300
301 if(hascap==0)
302 {
303 CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, groupedavp) );
304 }
305 strcpy(result,"DIAMETER_SUCCESS");
306 }
307 else if(auth_type==1)
308 {//Deregistration
309 if(sipserver_uri==NULL)
310 {
311 strcpy(result,"DIAMETER_ERROR_IDENTITY_NOT_REGISTERED");
312 }
313 else
314 {
315 strcpy(result,"DIAMETER_SUCCESS");
316 }
317 }
318 else
319 {//We should never be here!!
320 strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
321 goto out;
322 }
323 }
324
325
326out:
327 CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) );
328
329
330 //fd_msg_dump_walk(INFO,ans);
331
332 CHECK_FCT( fd_msg_send( msg, NULL, NULL ));
333
334
335
336 return 0;
337}