Modifying the return value of cfg_set* functions, in order to make
[sip-router] / id.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2005 iptelorg GmbH
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser 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  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License 
24  * along with this program; if not, write to the Free Software 
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27
28 #include "id.h"
29 #include "parser/parse_from.h"
30 #include "parser/parse_uri.h"
31 #include "parser/digest/digest.h"
32 #include "ut.h"
33
34 static str uid_name = STR_STATIC_INIT(AVP_UID);
35 static str did_name = STR_STATIC_INIT(AVP_DID);
36
37
38 /*
39  * Set From UID
40  */
41 int set_from_uid(str* uid)
42 {
43         struct search_state s;
44         int_str val, name;
45         avp_t* a;
46
47         name.s = uid_name;
48         a = search_first_avp(AVP_CLASS_USER | AVP_TRACK_FROM | AVP_NAME_STR, name, 0, &s);
49         while(a) {
50                 destroy_avp(a);
51                 a = search_next_avp(&s, 0);
52         }
53
54         val.s = *uid;
55         return add_avp(AVP_CLASS_USER | AVP_TRACK_FROM | AVP_NAME_STR | AVP_VAL_STR, name, val);
56 }
57
58
59 /* Extract username attribute from authorized credentials */
60 static inline str* cred_user(struct sip_msg* msg)
61 {
62         struct hdr_field* h;
63         auth_body_t* cred;
64
65         get_authorized_cred(msg->proxy_auth, &h);
66         if (!h) get_authorized_cred(msg->authorization, &h);
67         if (!h) return 0;
68         cred = (auth_body_t*)(h->parsed);
69         if (!cred || !cred->digest.username.user.len) return 0;
70         return &cred->digest.username.user;
71 }
72
73 /*
74  * Set From UID
75  */
76 int get_from_uid(str* uid, struct sip_msg* msg)
77 {
78         static char buf[MAX_URI_SIZE];
79         struct to_body* from;
80         struct sip_uri puri;
81         str* du;
82         int_str val, name;
83
84         name.s = uid_name;
85         if (search_first_avp(AVP_CLASS_USER | AVP_TRACK_FROM | AVP_NAME_STR, name, &val, 0)) {
86                 *uid = val.s;
87                 return 1;
88         } else {
89                 du = cred_user(msg);
90                 if (du) {
91                              /* Try digest username first */
92                         *uid = *du;
93                 } else {
94                              /* Get From URI username */
95                         if (parse_from_header(msg) < 0) {
96                                 LOG(L_ERR, "get_from_uid: Error while parsing From header\n");
97                                 return -1;
98                         }
99                         from = get_from(msg);
100                         if (parse_uri(from->uri.s, from->uri.len, &puri) == -1) {
101                                 LOG(L_ERR, "get_from_uid: Error while parsing From URI\n");
102                                 return -1;
103                         }
104                 
105                         if (puri.user.len > MAX_URI_SIZE) {
106                                 LOG(L_ERR, "get_from_uid: Username too long\n");
107                                 return -1;
108                         }
109                         memcpy(buf, puri.user.s, puri.user.len);
110                         uid->s = buf;
111                         uid->len = puri.user.len;
112                         strlower(uid);
113                 }
114                 
115                 val.s = *uid;
116                 add_avp(AVP_CLASS_USER | AVP_TRACK_FROM | AVP_NAME_STR | AVP_VAL_STR, name, val);
117                 return 0;
118         }
119 }
120
121
122 /*
123  * Set To UID
124  */
125 int set_to_uid(str* uid)
126 {
127         struct search_state s;
128         int_str val, name;
129         avp_t* a;
130
131         name.s = uid_name;
132         a = search_first_avp(AVP_CLASS_USER | AVP_TRACK_TO | AVP_NAME_STR, name, 0, &s);
133         while(a) {
134                 destroy_avp(a);
135                 a = search_next_avp(&s, 0);
136         }
137
138         val.s = *uid;
139         return add_avp(AVP_CLASS_USER | AVP_TRACK_TO | AVP_NAME_STR | AVP_VAL_STR, name, val);
140 }
141
142
143 /*
144  * Get To UID
145  */
146 int get_to_uid(str* uid, struct sip_msg* msg)
147 {
148         static char buf[MAX_URI_SIZE];
149         struct to_body* to;
150         struct sip_uri puri;
151         int_str val, name;
152
153         name.s = uid_name;
154         if (search_first_avp(AVP_CLASS_USER | AVP_TRACK_TO | AVP_NAME_STR, name, &val, 0)) {
155                 *uid = val.s;
156                 return 1;
157         } else {
158                 if ((msg->to==0) && 
159                                 (parse_headers(msg, HDR_TO_F, 0)<0 || msg->to==0)) {
160                         LOG(L_ERR, "get_to_uid: Error while parsing To URI: "
161                                         " to header bad or missing\n");
162                         return -1;
163                 }
164                 to = get_to(msg);
165                 if (parse_uri(to->uri.s, to->uri.len, &puri) == -1) {
166                         LOG(L_ERR, "get_to_uid: Error while parsing To URI\n");
167                         return -1;
168                 }
169                 
170                 if (puri.user.len > MAX_URI_SIZE) {
171                         LOG(L_ERR, "get_to_uid: Username too long\n");
172                         return -1;
173                 }
174                 memcpy(buf, puri.user.s, puri.user.len);
175                 uid->s = buf;
176                 uid->len = puri.user.len;
177                 strlower(uid);
178
179                 val.s = *uid;
180                 add_avp(AVP_CLASS_USER | AVP_TRACK_TO | AVP_NAME_STR | AVP_VAL_STR, name, val);
181                 return 0;
182         }
183 }
184
185
186 /*
187  * Return current To domain id
188  */
189 int get_to_did(str* did, struct sip_msg* msg)
190 {
191         int_str val, name;
192
193         name.s = did_name;
194         if (search_first_avp(AVP_TRACK_TO | AVP_NAME_STR, name, &val, 0)) {
195                 *did = val.s;
196                 return 1;
197         } 
198         return 0;
199 }
200
201
202 /*
203  * Return current To domain id
204  */
205 int get_from_did(str* did, struct sip_msg* msg)
206 {
207         int_str val, name;
208
209         name.s = did_name;
210         if (search_first_avp(AVP_TRACK_FROM | AVP_NAME_STR, name, &val, 0)) {
211                 *did = val.s;
212                 return 1;
213         } 
214         return 0;
215 }
216