Browse code

modules/auth_ephemeral: many improvements

- Some general tidying up of the code
- Support for both draft-uberti-rtcweb-turn-rest format usernames
and the original format
- New non-digest authenticate function that can be used to authenticate
WebSocket handshakes (based on URL and Cookie: contents) - this means no SIP
level authentication is required for WebSocket traffic
- Check functions to verify that the From:/To: URIs match the user-string part
of ephemeral usernames
- Check function so you can re-check the timestamp (for example, when caching the
ephemeral username during WebSocket handshakes you may want to check it is still
valid when a SIP request arrives)

Peter Dunkley authored on 19/09/2013 17:15:21
Showing 8 changed files
... ...
@@ -1,4 +1,3 @@
1
-
2 1
 Auth_ephemeral Module
3 2
 
4 3
 Peter Dunkley
... ...
@@ -6,8 +5,8 @@ Peter Dunkley
6 6
    Crocodile RCS Ltd
7 7
    <peter.dunkley@crocodile-rcs.com>
8 8
 
9
-   Copyright � 2013 Crocodile RCS Ltd
10
-     _________________________________________________________________
9
+   Copyright © 2013 Crocodile RCS Ltd
10
+     __________________________________________________________________
11 11
 
12 12
    Table of Contents
13 13
 
... ...
@@ -28,21 +27,31 @@ Peter Dunkley
28 28
         3. Parameters
29 29
 
30 30
               3.1. secret (string)
31
+              3.2. username_format (integer)
31 32
 
32 33
         4. Functions
33 34
 
34
-              4.1. autheph_proxy(realm) 
35
-              4.2. autheph_www(realm[, method]) 
36
-              4.3. autheph_check(realm) 
35
+              4.1. autheph_proxy(realm)
36
+              4.2. autheph_www(realm[, method])
37
+              4.3. autheph_check(realm)
38
+              4.4. autheph_authenticate(username, password)
39
+              4.5. autheph_check_from([username])
40
+              4.6. autheph_check_to([username])
41
+              4.7. autheph_check_timestamp(username)
37 42
 
38 43
    List of Examples
39 44
 
40 45
    1.1. Request example
41 46
    1.2. Response example
42 47
    1.3. secret parameter usage
43
-   1.4. autheph_proxy usage
44
-   1.5. autheph_www usage
45
-   1.6. autheph_check usage
48
+   1.4. username_format parameter usage
49
+   1.5. autheph_proxy usage
50
+   1.6. autheph_www usage
51
+   1.7. autheph_check usage
52
+   1.8. autheph_authenticate usage
53
+   1.9. autheph_check_from usage
54
+   1.10. autheph_check_to usage
55
+   1.11. autheph_check_timestamp usage
46 56
 
47 57
 Chapter 1. Admin Guide
48 58
 
... ...
@@ -63,12 +72,17 @@ Chapter 1. Admin Guide
63 63
    3. Parameters
64 64
 
65 65
         3.1. secret (string)
66
+        3.2. username_format (integer)
66 67
 
67 68
    4. Functions
68 69
 
69
-        4.1. autheph_proxy(realm) 
70
-        4.2. autheph_www(realm[, method]) 
71
-        4.3. autheph_check(realm) 
70
+        4.1. autheph_proxy(realm)
71
+        4.2. autheph_www(realm[, method])
72
+        4.3. autheph_check(realm)
73
+        4.4. autheph_authenticate(username, password)
74
+        4.5. autheph_check_from([username])
75
+        4.6. autheph_check_to([username])
76
+        4.7. autheph_check_timestamp(username)
72 77
 
73 78
 1. Overview
74 79
 
... ...
@@ -77,61 +91,59 @@ Chapter 1. Admin Guide
77 77
         1.1.1. Request
78 78
         1.1.2. Response
79 79
 
80
-   This  module  contains  all  authentication related functions that can
81
-   work  with  ephemeral credentials. This module should be used together
82
-   with  the  auth  module  -  it cannot be used independently because it
83
-   depends  on  the  auth  module.  Use  this  module  if you want to use
84
-   ephemeral credentials instead of ordinary usernames and passwords.
80
+   This module contains all authentication related functions that can work
81
+   with ephemeral credentials. This module can be used together with the
82
+   auth module for digest authentication. Use this module if you want to
83
+   use ephemeral credentials instead of ordinary usernames and passwords.
85 84
 
86 85
 1.1. How ephemeral credentials work
87 86
 
88
-   Ephemeral  credentials  are generated by a web-service and enforced on
89
-   Kamailio.  This  usage of ephemeral credentials ensures that access to
90
-   Kamailio  is controlled even if the credentials cannot be kept secret,
87
+   Ephemeral credentials are generated by a web-service and enforced on
88
+   Kamailio. This use of ephemeral credentials ensures that access to
89
+   Kamailio is controlled even if the credentials cannot be kept secret,
91 90
    as can be the case in WebRTC where the credentials may be specified in
92 91
    Javascript.
93 92
 
94
-   To  use  this  mechanism,  the  only  interaction  needed  between the
95
-   web-service and Kamailio is to share a secret key.
93
+   The only interaction needed between the web-service and Kamailio is to
94
+   share a secret key.
96 95
 
97
-   Typically, credentials will be requested from the web-service using an
98
-   HTTP  GET and provided in a JSON response. To prevent unauthorised use
99
-   the HTTP requests can be ACLd by various means.
96
+   Credentials will typically be requested from the web-service using an
97
+   HTTP POST and provided in a HTTP response with a content-type of
98
+   "application/json". To prevent unauthorised use the HTTP requests can
99
+   be ACLd by various means.
100 100
 
101
-   This mechanism is based on the Google proposal for a "TURN Server REST
102
-   API".
101
+   This mechanism is based on draft-uberti-rtcweb-turn-rest.
103 102
 
104 103
 1.1.1. Request
105 104
 
106
-   The request should contain the following parameters:
105
+   The request to the web-service should contain the following parameters:
107 106
      * service - specifies the desired service (msrp, sip, etc)
108
-     * username - an optional user identifier for the service
109
-     * ttl - an optional TTL request for the lifetime of the credentials,
110
-       in seconds.
107
+     * username - an optional user identifier for the service (as would
108
+       normally be found in the username parameter of an Authorization: or
109
+       Proxy-Authorization: header)
110
+     * key - an optional API key used for authentication
111 111
 
112 112
    Example 1.1. Request example
113
-GET /?service=sip&username=foobar;&ttl=86400;
113
+POST /?service=sip&username=foo@bar.com
114 114
 
115 115
 1.1.2. Response
116 116
 
117 117
    The response should include the following parameters:
118
-     * username  -  the  username  to  use  with  the service, which is a
119
-       combination  of  the  username  parameter  from  the request and a
120
-       timestamp in time_t format, colon-separated. If a username was not
121
-       included  in  the  request  this  parameter  will just include the
122
-       timestamp.
123
-     * password  -  the  password to use; this value is computed from the
124
-       secret   key  and  the  returned  username  value,  by  performing
118
+     * username - the username to use, which is a colon-delimited
119
+       combination of the expiration timestamp and the username parameter
120
+       from the request (if specified). When used with this module the
121
+       timestamp must be a UNIX timestamp.
122
+     * password - the password to use; this value is computed from the
123
+       secret key and the returned username value, by performing
125 124
        base64(hmac-sha1(secret key, returned username)).
126
-     * ttl  - the duration for which the username and password are valid,
127
-       in  seconds.  This  number  will  be  less  than  or  equal to the
128
-       requested TTL.
129
-     * uris  -  an array of URIs indicating servers that the username and
125
+     * ttl - the duration for which the username and password are valid,
126
+       in seconds.
127
+     * uris - an array of URIs indicating servers that the username and
130 128
        password are valid for.
131 129
 
132 130
    Example 1.2. Response example
133 131
 {
134
-  "username" : "foobar:1234567890",
132
+  "username" : "1234567890:foo@bar.com",
135 133
   "password" : "asdfghjklauio=",
136 134
   "ttl" : 86400,
137 135
   "uris" : [
... ...
@@ -148,7 +160,7 @@ GET /?service=sip&username=foobar;&ttl=86400;
148 148
 2.1. Kamailio Modules
149 149
 
150 150
    The module must be loaded before this module:
151
-     * auth.
151
+     * auth (optional).
152 152
 
153 153
 2.2. External Libraries or Applications
154 154
 
... ...
@@ -159,11 +171,12 @@ GET /?service=sip&username=foobar;&ttl=86400;
159 159
 3. Parameters
160 160
 
161 161
    3.1. secret (string)
162
+   3.2. username_format (integer)
162 163
 
163 164
 3.1. secret (string)
164 165
 
165
-   The  shared  secret  to use for generating credentials. This parameter
166
-   can  be  set  multiple  times  -  this enables the secret used for new
166
+   The shared secret to use for generating credentials. This parameter can
167
+   be set multiple times - this enables the secret used for new
167 168
    credentials to be changed without causing existing credentials to stop
168 169
    working. The last secret set is the first that will be tried.
169 170
 
... ...
@@ -172,28 +185,51 @@ GET /?service=sip&username=foobar;&ttl=86400;
172 172
 modparam("auth_ephemeral", "secret", "kamailio_rules")
173 173
 ...
174 174
 
175
+3.2. username_format (integer)
176
+
177
+   The format of the username in the web-service response.
178
+
179
+     * 0 (deprecated - pre IETF draft format) - <username parameter from
180
+       the request>:<timestamp>
181
+     * 1 (default - IETF draft format) - <timestamp>:<username parameter
182
+       from the request>
183
+
184
+   Example 1.4. username_format parameter usage
185
+...
186
+modparam("auth_ephemeral", "username_format", 0)
187
+...
188
+
175 189
 4. Functions
176 190
 
177
-   4.1. autheph_proxy(realm) 
178
-   4.2. autheph_www(realm[, method]) 
179
-   4.3. autheph_check(realm) 
191
+   4.1. autheph_proxy(realm)
192
+   4.2. autheph_www(realm[, method])
193
+   4.3. autheph_check(realm)
194
+   4.4. autheph_authenticate(username, password)
195
+   4.5. autheph_check_from([username])
196
+   4.6. autheph_check_to([username])
197
+   4.7. autheph_check_timestamp(username)
180 198
 
181 199
 4.1.  autheph_proxy(realm)
182 200
 
183
-   This function performs proxy authentication. the rest.
201
+   This function performs proxy authentication.
202
+
203
+Note
204
+
205
+   This function can only be used when the auth module is loaded before
206
+   this module.
184 207
 
185 208
    The meaning of the parameters are as follows:
186
-     * realm  -  Realm  is  an  opaque  string that the user agent should
187
-       present  to  the  user  so  that  he  can decide what username and
188
-       password  to use. Usually this is domain of the host the server is
209
+     * realm - realm is an opaque string that the user agent should
210
+       present to the user so that he can decide what username and
211
+       password to use. Usually this is domain of the host the server is
189 212
        running on.
190
-       It  must  not be an empty string "". Apart from a static string, a
213
+       It must not be an empty string “”. Apart from a static string, a
191 214
        typical value is the From-URI domain (i.e., $fd).
192 215
        The string may contain pseudo variables.
193 216
 
194 217
    This function can be used from REQUEST_ROUTE.
195 218
 
196
-   Example 1.4. autheph_proxy usage
219
+   Example 1.5. autheph_proxy usage
197 220
 ...
198 221
 if (!autheph_proxy("$fd")) {
199 222
     auth_challenge("$fd", "1");
... ...
@@ -205,21 +241,26 @@ if (!autheph_proxy("$fd")) {
205 205
 
206 206
    This function performs WWW digest authentication.
207 207
 
208
+Note
209
+
210
+   This function can only be used when the auth module is loaded before
211
+   this module.
212
+
208 213
    The meaning of the parameters are as follows:
209
-     * realm  -  Realm  is  an  opaque  string that the user agent should
210
-       present  to  the  user  so  that  he  can decide what username and
211
-       password  to use. Usually this is domain of the host the server is
214
+     * realm - realm is an opaque string that the user agent should
215
+       present to the user so that he can decide what username and
216
+       password to use. Usually this is domain of the host the server is
212 217
        running on.
213
-       It  must  not be an empty string "". Apart from a static string, a
218
+       It must not be an empty string “”. Apart from a static string, a
214 219
        typical value is the From-URI domain (i.e., $fd).
215 220
        The string may contain pseudo variables.
216
-     * method  - the method to be used for authentication. This parameter
221
+     * method - the method to be used for authentication. This parameter
217 222
        is optional and if not set the first "word" on the request-line is
218 223
        used.
219 224
 
220 225
    This function can be used from REQUEST_ROUTE.
221 226
 
222
-   Example 1.5. autheph_www usage
227
+   Example 1.6. autheph_www usage
223 228
 ...
224 229
 if (!autheph_www("$fd")) {
225 230
     auth_challenge("$fd", "1");
... ...
@@ -229,25 +270,154 @@ if (!autheph_www("$fd")) {
229 229
 
230 230
 4.3.  autheph_check(realm)
231 231
 
232
-   This   function   combines  the  functionalities  of  autheph_www  and
233
-   autheph_proxy,  the  first  being  exectuted  if  the SIP request is a
232
+   This function combines the functionalities of autheph_www and
233
+   autheph_proxy, the first being exectuted if the SIP request is a
234 234
    REGISTER, the second for the rest.
235 235
 
236
+Note
237
+
238
+   This function can only be used when the auth module is loaded before
239
+   this module.
240
+
236 241
    The meaning of the parameters are as follows:
237
-     * realm  -  Realm  is  an  opaque  string that the user agent should
238
-       present  to  the  user  so  that  he  can decide what username and
239
-       password  to use. Usually this is domain of the host the server is
242
+     * realm - realm is an opaque string that the user agent should
243
+       present to the user so that he can decide what username and
244
+       password to use. Usually this is domain of the host the server is
240 245
        running on.
241
-       It  must  not be an empty string "". Apart from a static string, a
246
+       It must not be an empty string “”. Apart from a static string, a
242 247
        typical value is the From-URI domain (i.e., $fd).
243 248
        The string may contain pseudo variables.
244 249
 
245 250
    This function can be used from REQUEST_ROUTE.
246 251
 
247
-   Example 1.6. autheph_check usage
252
+   Example 1.7. autheph_check usage
248 253
 ...
249 254
 if (!autheph_check("$fd")) {
250 255
     auth_challenge("$fd", "1");
251 256
     exit;
252 257
 }
253 258
 ...
259
+
260
+4.4.  autheph_authenticate(username, password)
261
+
262
+   This function performs non-digest ephemeral authentication. This may be
263
+   used when digest authentication cannot. For example, during WebSocket
264
+   handshake the username may be part of the requested URI and the
265
+   password presented in a Cookie: header.
266
+
267
+Note
268
+
269
+   This function may be used without loading the auth module.
270
+
271
+   The meaning of the parameters are as follows:
272
+     * username - the username returned in the response from the
273
+       web-service.
274
+     * password - the password returned in the response from the
275
+       web-service.
276
+
277
+   This function can be used from REQUEST_ROUTE.
278
+
279
+   Example 1.8. autheph_authenticate usage
280
+...
281
+if (!autheph_authenticate("$var(username)", "$var(password)")) {
282
+    sl_send_reply("403", "Forbidden");
283
+    exit;
284
+}
285
+...
286
+
287
+4.5.  autheph_check_from([username])
288
+
289
+   This function checks that the username (or username and domain) in the
290
+   From: URI matches the credentials.
291
+
292
+   When used without the username parameter it compares the From: URI with
293
+   the credentials used to authenticate the request (in the Authorization:
294
+   or Proxy-Authorization: headers).
295
+
296
+   The username parameter can be used to check the From: when individual
297
+   SIP requests are not authenticated (for example, when they are over
298
+   WebSockets and the connection was authenticated during the handshake).
299
+   In this scenario the username should be cached (perhaps in a
300
+   hash-table) at the point the authentication occurs.
301
+
302
+Note
303
+
304
+   This function must have the optional username parameter specified to
305
+   use it without loading the auth module before this module.
306
+
307
+   The meaning of the parameters are as follows:
308
+     * username (optional) - the username returned in the response from
309
+       the web-service.
310
+
311
+   This function can be used from REQUEST_ROUTE.
312
+
313
+   Example 1.9. autheph_check_from usage
314
+...
315
+if (!autheph_check_from()) {
316
+    sl_send_reply("403", "Forbidden");
317
+    exit;
318
+}
319
+...
320
+
321
+4.6.  autheph_check_to([username])
322
+
323
+   This function checks that the username (or username and domain) in the
324
+   To: URI matches the credentials.
325
+
326
+   When used without the username parameter it compares the To: URI with
327
+   the credentials used to authenticate the request (in the Authorization:
328
+   or Proxy-Authorization: headers).
329
+
330
+   The username parameter can be used to check the From: when individual
331
+   SIP requests are not authenticated (for example, when they are over
332
+   WebSockets and the connection was authenticated during the handshake).
333
+   In this scenario the username should be cached (perhaps in a
334
+   hash-table) at the point the authentication occurs.
335
+
336
+Note
337
+
338
+   This function must have the optional username parameter specified to
339
+   use it without loading the auth module before this module.
340
+
341
+   The meaning of the parameters are as follows:
342
+     * username (optional) - the username returned in the response from
343
+       the web-service.
344
+
345
+   This function can be used from REQUEST_ROUTE.
346
+
347
+   Example 1.10. autheph_check_to usage
348
+...
349
+if (!autheph_check_to()) {
350
+    sl_send_reply("403", "Forbidden");
351
+    exit;
352
+}
353
+...
354
+
355
+4.7.  autheph_check_timestamp(username)
356
+
357
+   This function checks that the timestamp in the username parameter has
358
+   not expired. The autheph_(check|proxy|www) functions all do this
359
+   automatically, but in a scenario when individual SIP requests are not
360
+   authenticated (for example, when they are over WebSockets and the
361
+   connection was authenticated during the handshake) you may want to
362
+   re-check for each new out-of-dialog request. In this scenario the
363
+   username should be cached (perhaps in a hash-table) at the point
364
+   authentication occurs.
365
+
366
+Note
367
+
368
+   This function may be used without loading the auth module.
369
+
370
+   The meaning of the parameters are as follows:
371
+     * username - the username returned in the response from the
372
+       web-service.
373
+
374
+   This function can be used from REQUEST_ROUTE.
375
+
376
+   Example 1.11. autheph_check_timestamp usage
377
+...
378
+if (!autheph_check_timestamp("$var(username)")) {
379
+    sl_send_reply("403", "Forbidden");
380
+    exit;
381
+}
382
+...
... ...
@@ -28,15 +28,18 @@
28 28
 
29 29
 #include "autheph_mod.h"
30 30
 #include "authorize.h"
31
+#include "checks.h"
31 32
 
32 33
 MODULE_VERSION
33 34
 
34 35
 static int mod_init(void);
35 36
 static void destroy(void);
36 37
 
37
-static int secret_param(modparam_t type, void* param);
38
+static int secret_param(modparam_t _type, void *_val);
38 39
 struct secret *secret_list = NULL;
39 40
 
41
+autheph_username_format_t autheph_username_format = AUTHEPH_USERNAME_IETF;
42
+
40 43
 auth_api_s_t eph_auth_api;
41 44
 
42 45
 static cmd_export_t cmds[]=
... ...
@@ -53,7 +56,24 @@ static cmd_export_t cmds[]=
53 53
 	{ "autheph_proxy", (cmd_function) autheph_proxy,
54 54
 	  1, fixup_var_str_1, 0,
55 55
 	  REQUEST_ROUTE },
56
-
56
+	{ "autheph_authenticate", (cmd_function) autheph_authenticate,
57
+	  2, fixup_var_str_12, 0,
58
+	  REQUEST_ROUTE },
59
+	{ "autheph_check_from", (cmd_function) autheph_check_from0,
60
+	  0, 0, 0,
61
+	  REQUEST_ROUTE },
62
+	{ "autheph_check_from", (cmd_function) autheph_check_from1,
63
+	  1, fixup_var_str_1, 0,
64
+	  REQUEST_ROUTE },
65
+	{ "autheph_check_to", (cmd_function) autheph_check_to0,
66
+	  0, 0, 0,
67
+	  REQUEST_ROUTE },
68
+	{ "autheph_check_to", (cmd_function) autheph_check_to1,
69
+	  1, fixup_var_str_1, 0,
70
+	  REQUEST_ROUTE },
71
+	{ "autheph_check_timestamp", (cmd_function) autheph_check_timestamp,
72
+	  1, fixup_var_str_1, 0,
73
+	  REQUEST_ROUTE },
57 74
 	{0, 0, 0, 0, 0, 0}
58 75
 };
59 76
 
... ...
@@ -61,6 +81,8 @@ static param_export_t params[]=
61 61
 {
62 62
 	{ "secret",		STR_PARAM|USE_FUNC_PARAM,
63 63
 	  (void *) secret_param },
64
+	{ "username_format",	INT_PARAM,
65
+	  &autheph_username_format },
64 66
 	{0, 0, 0}
65 67
 };
66 68
 
... ...
@@ -90,18 +112,38 @@ static int mod_init(void)
90 90
 		return -1;
91 91
 	}
92 92
 
93
-	bind_auth = (bind_auth_s_t) find_export("bind_auth_s", 0, 0);
94
-	if (!bind_auth)
93
+	switch(autheph_username_format)
95 94
 	{
96
-		LM_ERR("unable to find bind_auth function. Check if you have"
97
-			" loaded the auth module.\n");
98
-		return -2;
95
+	case AUTHEPH_USERNAME_NON_IETF:
96
+		LM_WARN("the %d value for the username_format modparam is "
97
+			"deprecated. You should update the web-service that "
98
+			"generates credentials to use the format specified in "
99
+			"draft-uberti-rtcweb-turn-rest.\n",
100
+			autheph_username_format);
101
+		/* Fall-thru */
102
+	case AUTHEPH_USERNAME_IETF:
103
+		break;
104
+
105
+	default:
106
+		LM_ERR("bad value for username_format modparam: %d\n",
107
+			autheph_username_format);
108
+		return -1;
99 109
 	}
100 110
 
101
-	if (bind_auth(&eph_auth_api) < 0)
111
+	bind_auth = (bind_auth_s_t) find_export("bind_auth_s", 0, 0);
112
+	if (bind_auth)
113
+	{
114
+		if (bind_auth(&eph_auth_api) < 0)
115
+		{
116
+			LM_ERR("unable to bind to auth module\n");
117
+			return -1;
118
+		}
119
+	}
120
+	else
102 121
 	{
103
-		LM_ERR("unable to bind to auth module\n");
104
-		return -3;
122
+		memset(&eph_auth_api, 0, sizeof(auth_api_s_t));
123
+		LM_INFO("auth module not loaded - digest authentication and "
124
+			"check functions will not be available\n");
105 125
 	}
106 126
 
107 127
 	return 0;
... ...
@@ -124,7 +166,7 @@ static void destroy(void)
124 124
 	}
125 125
 }
126 126
 
127
-static int add_secret(str secret_key)
127
+static inline int add_secret(str _secret_key)
128 128
 {
129 129
 	struct secret *secret_struct;
130 130
 
... ...
@@ -138,31 +180,31 @@ static int add_secret(str secret_key)
138 138
 	memset(secret_struct, 0, sizeof (struct secret));
139 139
 	secret_struct->next = secret_list;
140 140
 	secret_list = secret_struct;
141
-	secret_struct->secret_key = secret_key;
141
+	secret_struct->secret_key = _secret_key;
142 142
 
143 143
 	return 0;
144 144
 }
145 145
 
146
-static int secret_param(modparam_t type, void *val)
146
+static int secret_param(modparam_t _type, void *_val)
147 147
 {
148 148
 	str sval;
149 149
 
150
-	if (val == NULL)
150
+	if (_val == NULL)
151 151
 	{
152 152
 		LM_ERR("bad parameter\n");
153 153
 		return -1;
154 154
 	}
155 155
 
156
-	LM_INFO("adding %s to secret list\n", (char *) val);
156
+	LM_INFO("adding %s to secret list\n", (char *) _val);
157 157
 
158
-	sval.len = strlen((char *) val);
158
+	sval.len = strlen((char *) _val);
159 159
 	sval.s = (char *) shm_malloc(sizeof(char) * sval.len);
160 160
 	if (sval.s == NULL)
161 161
 	{
162 162
 		LM_ERR("unable to allocate shared memory\n");
163 163
 		return -1;
164 164
 	}
165
-	memcpy(sval.s, (char *) val, sval.len);
165
+	memcpy(sval.s, (char *) _val, sval.len);
166 166
 
167 167
 	return add_secret(sval);
168 168
 }
... ...
@@ -33,6 +33,12 @@ struct secret
33 33
 };
34 34
 extern struct secret *secret_list;
35 35
 
36
+typedef enum {
37
+	AUTHEPH_USERNAME_NON_IETF	= 0,
38
+	AUTHEPH_USERNAME_IETF		= 1,
39
+} autheph_username_format_t;
40
+extern autheph_username_format_t autheph_username_format;
41
+
36 42
 extern auth_api_s_t eph_auth_api;
37 43
 
38 44
 #endif /* AUTHEPH_MOD_H */
... ...
@@ -35,25 +35,41 @@
35 35
 #include "autheph_mod.h"
36 36
 #include "authorize.h"
37 37
 
38
-static inline int get_ha1(struct username* _username, str* _domain,
39
-				str* _secret, char* _ha1)
38
+static inline int get_pass(str *_username, str *_secret, str *_password)
40 39
 {
41 40
 	unsigned int hmac_len = SHA_DIGEST_LENGTH;
42 41
 	unsigned char hmac_sha1[hmac_len];
43
-	unsigned char password[base64_enc_len(hmac_len)];
44
-	str spassword;
45 42
 
46 43
 	if (HMAC(EVP_sha1(), _secret->s, _secret->len,
47
-			(unsigned char *) _username->whole.s,
48
-			_username->whole.len, hmac_sha1, &hmac_len) == NULL) {
44
+			(unsigned char *) _username->s,
45
+			_username->len, hmac_sha1, &hmac_len) == NULL)
46
+	{
49 47
 		LM_ERR("HMAC-SHA1 failed\n");
50 48
 		return -1;
51 49
 	}
52 50
 
53
-	spassword.len = base64_enc(hmac_sha1, hmac_len, password,
51
+	_password->len = base64_enc(hmac_sha1, hmac_len,
52
+					(unsigned char *) _password->s,
54 53
 					base64_enc_len(hmac_len));
54
+	LM_DBG("calculated password: %.*s\n", _password->len, _password->s);
55
+
56
+	return 0;
57
+}
58
+
59
+static inline int get_ha1(struct username *_username, str *_domain,
60
+				str *_secret, char *_ha1)
61
+{
62
+	char password[base64_enc_len(SHA_DIGEST_LENGTH)];
63
+	str spassword;
64
+
55 65
 	spassword.s = (char *) password;
56
-	LM_DBG("calculated password: %.*s\n", spassword.len, spassword.s);
66
+	spassword.len = 0;
67
+
68
+	if (get_pass(&_username->whole, _secret, &spassword) < 0)
69
+	{
70
+		LM_ERR("calculating password\n");
71
+		return -1;
72
+	}
57 73
 
58 74
 	eph_auth_api.calc_HA1(HA_MD5, &_username->whole, _domain, &spassword,
59 75
 				0, 0, _ha1);
... ...
@@ -62,25 +78,25 @@ static inline int get_ha1(struct username* _username, str* _domain,
62 62
 	return 0;
63 63
 }
64 64
 
65
-static int do_auth(struct sip_msg* msg, struct hdr_field *h, str *realm,
66
-			str *method, str* secret)
65
+static inline int do_auth(struct sip_msg *_m, struct hdr_field *_h, str *_realm,
66
+			str *_method, str *_secret)
67 67
 {
68 68
 	int ret;
69 69
 	char ha1[256];
70
-	auth_body_t *cred = (auth_body_t*) h->parsed;
70
+	auth_body_t *cred = (auth_body_t*) _h->parsed;
71 71
 
72
-	LM_DBG("secret: %.*s\n", secret->len, secret->s);
72
+	LM_DBG("secret: %.*s\n", _secret->len, _secret->s);
73 73
 
74
-	ret = get_ha1(&cred->digest.username, realm, secret, ha1);
75
-	if (ret < 0)
74
+	if (get_ha1(&cred->digest.username, _realm, _secret, ha1) < 0)
76 75
 	{
76
+		LM_ERR("calculating HA1\n");
77 77
 		return AUTH_ERROR;
78 78
 	}
79 79
 
80
-	ret = eph_auth_api.check_response(&(cred->digest), method, ha1);
80
+	ret = eph_auth_api.check_response(&cred->digest, _method, ha1);
81 81
 	if (ret == AUTHENTICATED)
82 82
 	{
83
-		if (eph_auth_api.post_auth(msg, h) != AUTHENTICATED)
83
+		if (eph_auth_api.post_auth(_m, _h) != AUTHENTICATED)
84 84
 		{
85 85
 			return AUTH_ERROR;
86 86
 		}
... ...
@@ -97,24 +113,39 @@ static int do_auth(struct sip_msg* msg, struct hdr_field *h, str *realm,
97 97
 	return AUTH_OK;
98 98
 }
99 99
 
100
-static int verify_timestamp(str* username)
100
+int autheph_verify_timestamp(str *_username)
101 101
 {
102 102
 	int pos = 0, cur_time = (int) time(NULL);
103 103
 	unsigned int expires;
104 104
 	str time_str = {0, 0};
105 105
 
106
-	while (pos < username->len && username->s[pos] != ':')
106
+	while (pos < _username->len && _username->s[pos] != ':')
107 107
 		pos++;
108 108
 
109
-	if (pos < username->len - 1)
109
+	if (autheph_username_format == AUTHEPH_USERNAME_NON_IETF)
110 110
 	{
111
-		time_str.s = username->s + pos + 1;
112
-		time_str.len = username->len - pos - 1;
111
+		if (pos < _username->len - 1)
112
+		{
113
+			time_str.s = _username->s + pos + 1;
114
+			time_str.len = _username->len - pos - 1;
115
+		}
116
+		else
117
+		{
118
+			time_str.s = _username->s;
119
+			time_str.len = _username->len;
120
+		}
113 121
 	}
114 122
 	else
115 123
 	{
116
-		time_str.s = username->s;
117
-		time_str.len = username->len;
124
+		time_str.s = _username->s;
125
+		if (pos < _username->len - 1)
126
+		{
127
+			time_str.len = pos;
128
+		}
129
+		else
130
+		{
131
+			time_str.len = _username->len;
132
+		}
118 133
 	}
119 134
 
120 135
 	LM_DBG("username timestamp: %.*s\n", time_str.len, time_str.s);
... ...
@@ -134,51 +165,52 @@ static int verify_timestamp(str* username)
134 134
 	return 0;
135 135
 }
136 136
 
137
-static int digest_authenticate(struct sip_msg* msg, str *realm,
138
-				hdr_types_t hftype, str *method)
137
+static inline int digest_authenticate(struct sip_msg *_m, str *_realm,
138
+				hdr_types_t _hftype, str *_method)
139 139
 {
140 140
 	struct hdr_field* h;
141 141
 	int ret;
142 142
 	struct secret *secret_struct = secret_list;
143 143
 	str username;
144 144
 
145
-	LM_DBG("realm: %.*s\n", realm->len, realm->s);
146
-	LM_DBG("method: %.*s\n", method->len, method->s);
147
-
148
-	ret = eph_auth_api.pre_auth(msg, realm, hftype, &h, NULL);
149
-	switch(ret) {
150
-		case NONCE_REUSED:
151
-			LM_DBG("nonce reused\n");
152
-			return AUTH_NONCE_REUSED;
153
-		case STALE_NONCE:
154
-			LM_DBG("stale nonce\n");
155
-			return AUTH_STALE_NONCE;
156
-		case NO_CREDENTIALS:
157
-			LM_DBG("no credentials\n");
158
-			return AUTH_NO_CREDENTIALS;
159
-		case ERROR:
160
-		case BAD_CREDENTIALS:
161
-			LM_DBG("error or bad credentials\n");
162
-			return AUTH_ERROR;
163
-		case CREATE_CHALLENGE:
164
-			LM_ERR("CREATE_CHALLENGE is not a valid state\n");
165
-			return AUTH_ERROR;
166
-		case DO_RESYNCHRONIZATION:
167
-			LM_ERR("DO_RESYNCHRONIZATION is not a valid state\n");
168
-			return AUTH_ERROR;
169
-		case NOT_AUTHENTICATED:
170
-			LM_DBG("not authenticated\n");
171
-			return AUTH_ERROR;
172
-		case DO_AUTHENTICATION:
173
-			break;
174
-		case AUTHENTICATED:
175
-			return AUTH_OK;
145
+	LM_DBG("realm: %.*s\n", _realm->len, _realm->s);
146
+	LM_DBG("method: %.*s\n", _method->len, _method->s);
147
+
148
+	ret = eph_auth_api.pre_auth(_m, _realm, _hftype, &h, NULL);
149
+	switch(ret)
150
+	{
151
+	case NONCE_REUSED:
152
+		LM_DBG("nonce reused\n");
153
+		return AUTH_NONCE_REUSED;
154
+	case STALE_NONCE:
155
+		LM_DBG("stale nonce\n");
156
+		return AUTH_STALE_NONCE;
157
+	case NO_CREDENTIALS:
158
+		LM_DBG("no credentials\n");
159
+		return AUTH_NO_CREDENTIALS;
160
+	case ERROR:
161
+	case BAD_CREDENTIALS:
162
+		LM_DBG("error or bad credentials\n");
163
+		return AUTH_ERROR;
164
+	case CREATE_CHALLENGE:
165
+		LM_ERR("CREATE_CHALLENGE is not a valid state\n");
166
+		return AUTH_ERROR;
167
+	case DO_RESYNCHRONIZATION:
168
+		LM_ERR("DO_RESYNCHRONIZATION is not a valid state\n");
169
+		return AUTH_ERROR;
170
+	case NOT_AUTHENTICATED:
171
+		LM_DBG("not authenticated\n");
172
+		return AUTH_ERROR;
173
+	case DO_AUTHENTICATION:
174
+		break;
175
+	case AUTHENTICATED:
176
+		return AUTH_OK;
176 177
 	}
177 178
 
178 179
 	username = ((auth_body_t *) h->parsed)->digest.username.whole;
179 180
 	LM_DBG("username: %.*s\n", username.len, username.s);
180 181
 
181
-	if (verify_timestamp(&username) < 0)
182
+	if (autheph_verify_timestamp(&username) < 0)
182 183
 	{
183 184
 		LM_ERR("invalid timestamp in username\n");
184 185
 		return AUTH_ERROR;
... ...
@@ -186,7 +218,7 @@ static int digest_authenticate(struct sip_msg* msg, str *realm,
186 186
 
187 187
 	while (secret_struct != NULL)
188 188
 	{
189
-		ret = do_auth(msg, h, realm, method,
189
+		ret = do_auth(_m, h, _realm, _method,
190 190
 				&secret_struct->secret_key);
191 191
 		if (ret == AUTH_OK)
192 192
 		{
... ...
@@ -198,16 +230,23 @@ static int digest_authenticate(struct sip_msg* msg, str *realm,
198 198
 	return ret;
199 199
 }
200 200
 
201
-int autheph_check(struct sip_msg* _m, char* _realm)
201
+int autheph_check(struct sip_msg *_m, char *_realm)
202 202
 {
203 203
 	str srealm;
204 204
 
205
-	if ((_m->REQ_METHOD == METHOD_ACK) || (_m->REQ_METHOD == METHOD_CANCEL))
205
+	if (eph_auth_api.pre_auth == NULL)
206
+	{
207
+		LM_ERR("autheph_check() cannot be used without the auth "
208
+			"module\n");
209
+		return AUTH_ERROR;
210
+	}
211
+
212
+	if (_m->REQ_METHOD == METHOD_ACK || _m->REQ_METHOD == METHOD_CANCEL)
206 213
 	{
207 214
 		return AUTH_OK;
208 215
 	}
209 216
 
210
-	if(_m==NULL || _realm==NULL)
217
+	if(_m == NULL || _realm == NULL)
211 218
 	{
212 219
 		LM_ERR("invalid parameters\n");
213 220
 		return AUTH_ERROR;
... ...
@@ -219,30 +258,41 @@ int autheph_check(struct sip_msg* _m, char* _realm)
219 219
 		return AUTH_ERROR;
220 220
 	}
221 221
 
222
-	if (srealm.len==0)
222
+	if (srealm.len == 0)
223 223
 	{
224 224
 		LM_ERR("invalid realm parameter - empty value\n");
225 225
 		return AUTH_ERROR;
226 226
 	}
227 227
 
228
-	if(_m->REQ_METHOD==METHOD_REGISTER)
228
+	if (_m->REQ_METHOD == METHOD_REGISTER)
229
+	{
229 230
 		return digest_authenticate(_m, &srealm, HDR_AUTHORIZATION_T,
230 231
 					&_m->first_line.u.request.method);
232
+	}
231 233
 	else
234
+	{
232 235
 		return digest_authenticate(_m, &srealm, HDR_PROXYAUTH_T,
233 236
 					&_m->first_line.u.request.method);
237
+	}
234 238
 }
235 239
 
236
-int autheph_www(struct sip_msg* _m, char* _realm)
240
+int autheph_www(struct sip_msg *_m, char *_realm)
237 241
 {
238 242
 	str srealm;
239 243
 
240
-	if ((_m->REQ_METHOD == METHOD_ACK) || (_m->REQ_METHOD == METHOD_CANCEL))
244
+	if (eph_auth_api.pre_auth == NULL)
245
+	{
246
+		LM_ERR("autheph_www() cannot be used without the auth "
247
+			"module\n");
248
+		return AUTH_ERROR;
249
+	}
250
+
251
+	if (_m->REQ_METHOD == METHOD_ACK || _m->REQ_METHOD == METHOD_CANCEL)
241 252
 	{
242 253
 		return AUTH_OK;
243 254
 	}
244 255
 
245
-	if(_m==NULL || _realm==NULL)
256
+	if(_m == NULL || _realm == NULL)
246 257
 	{
247 258
 		LM_ERR("invalid parameters\n");
248 259
 		return AUTH_ERROR;
... ...
@@ -254,7 +304,7 @@ int autheph_www(struct sip_msg* _m, char* _realm)
254 254
 		return AUTH_ERROR;
255 255
 	}
256 256
 
257
-	if (srealm.len==0)
257
+	if (srealm.len == 0)
258 258
 	{
259 259
 		LM_ERR("invalid realm parameter - empty value\n");
260 260
 		return AUTH_ERROR;
... ...
@@ -264,17 +314,24 @@ int autheph_www(struct sip_msg* _m, char* _realm)
264 264
 					&_m->first_line.u.request.method);
265 265
 }
266 266
 
267
-int autheph_www2(struct sip_msg* _m, char* _realm, char *_method)
267
+int autheph_www2(struct sip_msg *_m, char *_realm, char *_method)
268 268
 {
269 269
 	str srealm;
270 270
 	str smethod;
271 271
 
272
-	if ((_m->REQ_METHOD == METHOD_ACK) || (_m->REQ_METHOD == METHOD_CANCEL))
272
+	if (eph_auth_api.pre_auth == NULL)
273
+	{
274
+		LM_ERR("autheph_www() cannot be used without the auth "
275
+			"module\n");
276
+		return AUTH_ERROR;
277
+	}
278
+
279
+	if (_m->REQ_METHOD == METHOD_ACK || _m->REQ_METHOD == METHOD_CANCEL)
273 280
 	{
274 281
 		return AUTH_OK;
275 282
 	}
276 283
 
277
-	if(_m==NULL || _realm==NULL)
284
+	if(_m == NULL || _realm == NULL)
278 285
 	{
279 286
 		LM_ERR("invalid parameters\n");
280 287
 		return AUTH_ERROR;
... ...
@@ -286,7 +343,7 @@ int autheph_www2(struct sip_msg* _m, char* _realm, char *_method)
286 286
 		return AUTH_ERROR;
287 287
 	}
288 288
 
289
-	if (srealm.len==0)
289
+	if (srealm.len == 0)
290 290
 	{
291 291
 		LM_ERR("invalid realm parameter - empty value\n");
292 292
 		return AUTH_ERROR;
... ...
@@ -307,16 +364,23 @@ int autheph_www2(struct sip_msg* _m, char* _realm, char *_method)
307 307
 	return digest_authenticate(_m, &srealm, HDR_AUTHORIZATION_T, &smethod);
308 308
 }
309 309
 
310
-int autheph_proxy(struct sip_msg* _m, char* _realm)
310
+int autheph_proxy(struct sip_msg *_m, char *_realm)
311 311
 {
312 312
 	str srealm;
313 313
 
314
-	if ((_m->REQ_METHOD == METHOD_ACK) || (_m->REQ_METHOD == METHOD_CANCEL))
314
+	if (eph_auth_api.pre_auth == NULL)
315
+	{
316
+		LM_ERR("autheph_proxy() cannot be used without the auth "
317
+			"module\n");
318
+		return AUTH_ERROR;
319
+	}
320
+
321
+	if (_m->REQ_METHOD == METHOD_ACK || _m->REQ_METHOD == METHOD_CANCEL)
315 322
 	{
316 323
 		return AUTH_OK;
317 324
 	}
318 325
 
319
-	if(_m==NULL || _realm==NULL)
326
+	if(_m == NULL || _realm == NULL)
320 327
 	{
321 328
 		LM_ERR("invalid parameters\n");
322 329
 		return AUTH_ERROR;
... ...
@@ -328,7 +392,7 @@ int autheph_proxy(struct sip_msg* _m, char* _realm)
328 328
 		return AUTH_ERROR;
329 329
 	}
330 330
 
331
-	if (srealm.len==0)
331
+	if (srealm.len == 0)
332 332
 	{
333 333
 		LM_ERR("invalid realm parameter - empty value\n");
334 334
 		return AUTH_ERROR;
... ...
@@ -337,3 +401,72 @@ int autheph_proxy(struct sip_msg* _m, char* _realm)
337 337
 	return digest_authenticate(_m, &srealm, HDR_PROXYAUTH_T,
338 338
 					&_m->first_line.u.request.method);
339 339
 }
340
+
341
+int autheph_authenticate(struct sip_msg *_m, char *_username, char *_password)
342
+{
343
+	str susername, spassword;
344
+	char generated_password[base64_enc_len(SHA_DIGEST_LENGTH)];
345
+	str sgenerated_password;
346
+	struct secret *secret_struct = secret_list;
347
+
348
+	if (_m == NULL || _username == NULL || _password == NULL)
349
+	{
350
+		LM_ERR("invalid parameters\n");
351
+		return AUTH_ERROR;
352
+	}
353
+
354
+	if (get_str_fparam(&susername, _m, (fparam_t*)_username) < 0)
355
+	{
356
+		LM_ERR("failed to get username value\n");
357
+		return AUTH_ERROR;
358
+	}
359
+
360
+	if (susername.len == 0)
361
+	{
362
+		LM_ERR("invalid username parameter - empty value\n");
363
+		return AUTH_ERROR;
364
+	}
365
+
366
+	if (get_str_fparam(&spassword, _m, (fparam_t*)_password) < 0)
367
+	{
368
+		LM_ERR("failed to get password value\n");
369
+		return AUTH_ERROR;
370
+	}
371
+
372
+	if (spassword.len == 0)
373
+	{
374
+		LM_ERR("invalid password parameter - empty value\n");
375
+		return AUTH_ERROR;
376
+	}
377
+
378
+	if (autheph_verify_timestamp(&susername) < 0)
379
+	{
380
+		LM_ERR("invalid timestamp in username\n");
381
+		return AUTH_ERROR;
382
+	}
383
+
384
+	LM_DBG("username: %.*s\n", susername.len, susername.s);
385
+	LM_DBG("password: %.*s\n", spassword.len, spassword.s);
386
+
387
+	sgenerated_password.s = generated_password;
388
+	while (secret_struct != NULL)
389
+	{
390
+		LM_DBG("trying secret: %.*s\n",
391
+			secret_struct->secret_key.len,
392
+			secret_struct->secret_key.s);
393
+		if (get_pass(&susername, &secret_struct->secret_key,
394
+				&sgenerated_password) == 0)
395
+		{
396
+			LM_DBG("generated password: %.*s\n",
397
+				sgenerated_password.len, sgenerated_password.s);
398
+			if (strncmp(spassword.s, sgenerated_password.s,
399
+					spassword.len) == 0)
400
+			{
401
+				return AUTH_OK;
402
+			}
403
+		}
404
+		secret_struct = secret_struct->next;
405
+	}
406
+
407
+	return AUTH_ERROR;
408
+}
... ...
@@ -23,11 +23,15 @@
23 23
 #ifndef AUTHORIZE_H
24 24
 #define AUTHORIZE_H
25 25
 
26
+#include "../../str.h"
26 27
 #include "../../parser/msg_parser.h"
27 28
 
28
-int autheph_check(struct sip_msg* _m, char* _realm);
29
-int autheph_www(struct sip_msg* _m, char* _realm);
30
-int autheph_www2(struct sip_msg* _m, char* _realm, char *_method);
31
-int autheph_proxy(struct sip_msg* _m, char* _realm);
29
+int autheph_verify_timestamp(str *_username);
30
+
31
+int autheph_check(struct sip_msg *_m, char *_realm);
32
+int autheph_www(struct sip_msg *_m, char *_realm);
33
+int autheph_www2(struct sip_msg *_m, char *_realm, char *_method);
34
+int autheph_proxy(struct sip_msg *_m, char *_realm);
35
+int autheph_authenticate(struct sip_msg *_m, char *_username, char *_password);
32 36
 
33 37
 #endif /* AUTHORIZE_H */
34 38
new file mode 100644
... ...
@@ -0,0 +1,282 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2013 Crocodile RCS Ltd
4
+ *
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * Kamailio is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * Kamailio is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License 
18
+ * along with this program; if not, write to the Free Software 
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ *
21
+ */
22
+#include "../../dprint.h"
23
+#include "../../mod_fix.h"
24
+#include "../../str.h"
25
+#include "../../ut.h"
26
+#include "../../parser/digest/digest.h"
27
+#include "../../parser/parse_from.h"
28
+#include "../../parser/parse_uri.h"
29
+#include "../../mod_fix.h"
30
+
31
+#include "autheph_mod.h"
32
+#include "authorize.h"
33
+#include "checks.h"
34
+
35
+static inline int check_username(str *_username, struct sip_uri *_uri)
36
+{
37
+	str uname, domain = {0, 0};
38
+	int pos = 0;
39
+
40
+	if (_username == NULL || _username->len == 0)
41
+	{
42
+		LM_ERR("invalid username\n");
43
+		return CHECK_ERROR;
44
+	}
45
+
46
+	while (pos < _username->len && _username->s[pos] != ':')
47
+		pos++;
48
+
49
+	if (pos < _username->len - 1)
50
+	{
51
+		if (autheph_username_format == AUTHEPH_USERNAME_NON_IETF)
52
+		{
53
+			uname.s = _username->s;
54
+			uname.len = pos;
55
+		}
56
+		else
57
+		{
58
+			uname.s = _username->s + pos + 1;
59
+			uname.len = _username->len - pos - 1;
60
+		}
61
+	}
62
+	else
63
+	{
64
+		return CHECK_NO_USER;
65
+	}
66
+
67
+	pos = 0;
68
+	while (pos < uname.len && uname.s[pos] != '@')
69
+		pos++;
70
+
71
+	if (pos < uname.len - 1)
72
+	{
73
+		domain.s = uname.s + pos + 1;
74
+		domain.len = uname.len - pos - 1;
75
+		uname.len = pos;
76
+	}
77
+
78
+	if (uname.len == _uri->user.len
79
+		&& strncmp(uname.s, _uri->user.s, uname.len) == 0)
80
+	{
81
+		if (domain.len == 0)
82
+		{
83
+			return CHECK_OK;
84
+		}
85
+		else if (domain.len == _uri->host.len
86
+			&& strncmp(domain.s, _uri->host.s, domain.len) == 0)
87
+		{
88
+			return CHECK_OK;
89
+		}
90
+	}
91
+
92
+	return CHECK_ERROR;
93
+}
94
+
95
+static inline int check_from(struct sip_msg *_m, str *_username)
96
+{
97
+	if (parse_from_header(_m) < 0)
98
+	{
99
+		LM_ERR("parsing From: header\n");
100
+		return CHECK_ERROR;
101
+	}
102
+
103
+	if (parse_from_uri(_m) == NULL)
104
+	{
105
+		LM_ERR("parsing From: URI\n");
106
+		return CHECK_ERROR;
107
+	}
108
+
109
+	return check_username(_username, &get_from(_m)->parsed_uri);
110
+}
111
+
112
+static inline int get_cred(struct sip_msg *_m, str *_username)
113
+{
114
+	struct hdr_field *h;
115
+
116
+	get_authorized_cred(_m->authorization, &h);
117
+	if (!h)
118
+	{
119
+		get_authorized_cred(_m->proxy_auth, &h);
120
+		if (!h)
121
+		{
122
+			LM_ERR("No authorized credentials found\n");
123
+			return -1;
124
+		}
125
+	}
126
+
127
+	*_username = ((auth_body_t *) h->parsed)->digest.username.whole;
128
+	return 0;
129
+}
130
+
131
+int autheph_check_from0(struct sip_msg *_m)
132
+{
133
+	str username = {0, 0};
134
+
135
+	if (eph_auth_api.pre_auth == NULL)
136
+	{
137
+		LM_ERR("autheph_check_from() with no username parameter "
138
+			"cannot be used without the auth module\n");
139
+		return CHECK_ERROR;
140
+	}
141
+
142
+	if (_m == NULL)
143
+	{
144
+		LM_ERR("invalid parameters\n");
145
+		return CHECK_ERROR;
146
+	}
147
+
148
+	if (get_cred(_m, &username) < 0)
149
+	{
150
+		LM_ERR("call autheph_(check|proxy|www) before calling "
151
+			" check_from() with no username parameter\n");
152
+		return CHECK_ERROR;
153
+	}
154
+
155
+	return check_from(_m, &username);
156
+}
157
+
158
+int autheph_check_from1(struct sip_msg *_m, char *_username)
159
+{
160
+	str susername;
161
+
162
+	if (_m == NULL || _username == NULL)
163
+	{
164
+		LM_ERR("invalid parameters\n");
165
+		return CHECK_ERROR;
166
+	}
167
+
168
+	if (get_str_fparam(&susername, _m, (fparam_t*)_username) < 0)
169
+	{
170
+		LM_ERR("failed to get username value\n");
171
+		return CHECK_ERROR;
172
+	}
173
+
174
+	if (susername.len == 0)
175
+	{
176
+		LM_ERR("invalid username parameter - empty value\n");
177
+		return CHECK_ERROR;
178
+	}
179
+
180
+
181
+	return check_from(_m, &susername);
182
+}
183
+
184
+static inline int check_to(struct sip_msg *_m, str *_username)
185
+{
186
+	if (!_m->to && ((parse_headers(_m, HDR_TO_F, 0) == -1) || (!_m->to)))
187
+	{
188
+		LM_ERR("parsing To: header\n");
189
+		return CHECK_ERROR;
190
+	}
191
+
192
+	if (parse_to_uri(_m) == NULL)
193
+	{
194
+		LM_ERR("parsing To: URI\n");
195
+		return CHECK_ERROR;
196
+	}
197
+
198
+	return check_username(_username, &get_to(_m)->parsed_uri);
199
+}
200
+
201
+int autheph_check_to0(struct sip_msg *_m)
202
+{
203
+	str username = {0, 0};
204
+
205
+	if (eph_auth_api.pre_auth == NULL)
206
+	{
207
+		LM_ERR("autheph_check_to() with no username parameter "
208
+			"cannot be used without the auth module\n");
209
+		return CHECK_ERROR;
210
+	}
211
+
212
+	if (_m == NULL)
213
+	{
214
+		LM_ERR("invalid parameters\n");
215
+		return CHECK_ERROR;
216
+	}
217
+
218
+	if (get_cred(_m, &username) < 0)
219
+	{
220
+		LM_ERR("call autheph_(check|proxy|www) before calling "
221
+			" check_to() with no username parameter\n");
222
+		return CHECK_ERROR;
223
+	}
224
+
225
+	return check_to(_m, &username);
226
+}
227
+
228
+int autheph_check_to1(struct sip_msg *_m, char *_username)
229
+{
230
+	str susername;
231
+
232
+	if (_m == NULL || _username == NULL)
233
+	{
234
+		LM_ERR("invalid parameters\n");
235
+		return CHECK_ERROR;
236
+	}
237
+
238
+	if (get_str_fparam(&susername, _m, (fparam_t*)_username) < 0)
239
+	{
240
+		LM_ERR("failed to get username value\n");
241
+		return CHECK_ERROR;
242
+	}
243
+
244
+	if (susername.len == 0)
245
+	{
246
+		LM_ERR("invalid username parameter - empty value\n");
247
+		return CHECK_ERROR;
248
+	}
249
+
250
+	return check_to(_m, &susername);
251
+}
252
+
253
+int autheph_check_timestamp(struct sip_msg *_m, char *_username)
254
+{
255
+	str susername;
256
+
257
+	if (_m == NULL || _username == NULL)
258
+	{
259
+		LM_ERR("invalid parameters\n");
260
+		return CHECK_ERROR;
261
+	}
262
+
263
+	if (get_str_fparam(&susername, _m, (fparam_t*)_username) < 0)
264
+	{
265
+		LM_ERR("failed to get username value\n");
266
+		return CHECK_ERROR;
267
+	}
268
+
269
+	if (susername.len == 0)
270
+	{
271
+		LM_ERR("invalid username parameter - empty value\n");
272
+		return CHECK_ERROR;
273
+	}
274
+
275
+	if (autheph_verify_timestamp(&susername) < 0)
276
+	{
277
+		return CHECK_ERROR;
278
+	}
279
+
280
+	return CHECK_OK;
281
+}
0 282
new file mode 100644
... ...
@@ -0,0 +1,40 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2013 Crocodile RCS Ltd
4
+ *
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * Kamailio is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * Kamailio is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License 
18
+ * along with this program; if not, write to the Free Software 
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ *
21
+ */
22
+#ifndef CHECKS_H
23
+#define CHECKS_H
24
+
25
+#include "../../parser/msg_parser.h"
26
+
27
+int autheph_check_from0(struct sip_msg *_m);
28
+int autheph_check_from1(struct sip_msg *_m, char *_username);
29
+int autheph_check_to0(struct sip_msg *_m);
30
+int autheph_check_to1(struct sip_msg *_m, char *_username);
31
+int autheph_check_timestamp(struct sip_msg *_m, char *_username);
32
+
33
+typedef enum {
34
+	CHECK_NO_USER	= -2,
35
+	CHECK_ERROR	= -1,
36
+	CHECK_OK	= 1
37
+} autheph_check_result_t;
38
+
39
+#endif /* CHECKS_H */
... ...
@@ -18,38 +18,38 @@
18 18
 	<title>Overview</title>
19 19
 	<para>
20 20
 	This module contains all authentication related functions that can work
21
-	with ephemeral credentials. This module should be used together with the
22
-	auth module - it cannot be used independently because it depends on the
23
-	auth module. Use this module if you want to use ephemeral credentials
24
-	instead of ordinary usernames and passwords.
21
+	with ephemeral credentials. This module can be used together with the
22
+	<emphasis>auth</emphasis> module for digest authentication. Use this
23
+	module if you want to use ephemeral credentials instead of ordinary
24
+	usernames and passwords.
25 25
 	</para>
26