Browse code

Fast digest parser

Jan Janak authored on 09/08/2002 11:11:53
Showing 7 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,192 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Digest credentials parser interface
5
+ */
6
+
7
+#include "digest.h"
8
+#include "../../mem/mem.h"  /* pkg_malloc */
9
+#include "../../dprint.h"
10
+#include <stdio.h>          /* printf */
11
+
12
+
13
+static inline int new_credentials(struct hdr_field* _h)
14
+{
15
+	auth_body_t* b;
16
+
17
+	b = (auth_body_t*)(_h->parsed);
18
+
19
+	if (b) {
20
+		DBG("parse_credentials(): Credentials already parsed\n");
21
+		return -1;
22
+	}
23
+
24
+	b = (auth_body_t*)pkg_malloc(sizeof(auth_body_t));
25
+	if (!b) {
26
+		LOG(L_ERR, "parse_credentials(): No memory left\n");
27
+		return -2;
28
+	}
29
+		
30
+	init_dig_cred(&(b->digest));
31
+	b->stale = 0;
32
+	b->nonce_retries = 0;
33
+	b->authorized = 0;
34
+
35
+	_h->parsed = (void*)b;
36
+
37
+	return 0;
38
+}
39
+
40
+
41
+int parse_credentials(struct hdr_field* _h)
42
+{
43
+	int res;
44
+
45
+	if (new_credentials(_h) < 0) {
46
+		LOG(L_ERR, "parse_credentials(): Can't create new credentials\n");
47
+		return -1;
48
+	}
49
+
50
+	res = parse_digest_cred(&(_h->body), &(((auth_body_t*)(_h->parsed))->digest));
51
+	
52
+	if (res != 0) {
53
+		free_credentials((auth_body_t**)&(_h->parsed));
54
+	}
55
+
56
+	return res;
57
+}
58
+
59
+
60
+void free_credentials(auth_body_t** _b)
61
+{
62
+	pkg_free(*_b);
63
+	*_b = 0;
64
+}
65
+
66
+
67
+/*
68
+ * Check semantics of a digest credentials structure
69
+ * Make sure that all attributes needed to verify response 
70
+ * string are set or at least have a default value
71
+ *
72
+ * The returned value is logical OR of all errors encountered
73
+ * during the check, see dig_err_t type for more details 
74
+ */
75
+dig_err_t check_dig_cred(dig_cred_t* _c)
76
+{
77
+	dig_err_t res = E_DIG_OK;
78
+
79
+	     /* Username must be present */
80
+	if (_c->username.s == 0) res |= E_DIG_USERNAME;
81
+
82
+	     /* Realm must be present */
83
+	if (_c->realm.s == 0) res |= E_DIG_REALM;
84
+
85
+	     /* Nonce that was used must be specified */
86
+	if (_c->nonce.s == 0) res |= E_DIG_NONCE;
87
+
88
+	     /* URI must be specified */
89
+	if (_c->uri.s == 0) res |= E_DIG_URI;
90
+
91
+	     /* We cannot check credentials without response */
92
+	if (_c->response.s == 0) res |= E_DIG_RESPONSE;
93
+
94
+	     /* If QOP parameter is present, some additional
95
+	      * requirements must be met
96
+	      */
97
+	if ((_c->qop.qop_parsed == QOP_AUTH) || (_c->qop.qop_parsed == QOP_AUTHINT)) {
98
+		     /* CNONCE must be specified */
99
+		if (_c->cnonce.s == 0) res |= E_DIG_CNONCE;
100
+		     /* and also nonce count must be specified */
101
+		if (_c->nc.s == 0) res |= E_DIG_NC;
102
+	}
103
+		
104
+	return res;	
105
+}
106
+
107
+
108
+/*
109
+ * Print credential structure content to stdout
110
+ * Just for debugging
111
+ */
112
+void print_cred(dig_cred_t* _c)
113
+{
114
+	printf("===Digest credentials===\n");
115
+	if (_c) {
116
+		printf("Username  = \'%.*s\'\n", _c->username.len, _c->username.s);
117
+		printf("Realm     = \'%.*s\'\n", _c->realm.len, _c->realm.s);
118
+		printf("Nonce     = \'%.*s\'\n", _c->nonce.len, _c->nonce.s);
119
+		printf("URI       = \'%.*s\'\n", _c->uri.len, _c->uri.s);
120
+		printf("Response  = \'%.*s\'\n", _c->response.len, _c->response.s);
121
+		printf("Algorithm = \'%.*s\'\n", _c->alg.alg_str.len, _c->alg.alg_str.s);
122
+		printf("\\--parsed = ");
123
+
124
+		switch(_c->alg.alg_parsed) {
125
+		case ALG_UNSPEC:  printf("ALG_UNSPEC\n");  break;
126
+		case ALG_MD5:     printf("ALG_MD5\n");     break;
127
+		case ALG_MD5SESS: printf("ALG_MD5SESS\n"); break;
128
+		case ALG_OTHER:   printf("ALG_OTHER\n");   break;
129
+		}
130
+
131
+		printf("Cnonce    = \'%.*s\'\n", _c->cnonce.len, _c->cnonce.s);
132
+		printf("Opaque    = \'%.*s\'\n", _c->opaque.len, _c->opaque.s);
133
+		printf("QOP       = \'%.*s\'\n", _c->qop.qop_str.len, _c->qop.qop_str.s);
134
+		printf("\\--parsed = ");
135
+
136
+		switch(_c->qop.qop_parsed) {
137
+		case QOP_UNSPEC:  printf("QOP_UNSPEC\n");  break;
138
+		case QOP_AUTH:    printf("QOP_AUTH\n");    break;
139
+		case QOP_AUTHINT: printf("QOP_AUTHINT\n"); break;
140
+		case QOP_OTHER:   printf("QOP_OTHER\n");   break;
141
+		}
142
+		printf("NC        = \'%.*s\'\n", _c->nc.len, _c->nc.s);
143
+	}
144
+	printf("===/Digest credentials===\n");
145
+}
146
+
147
+
148
+/*
149
+ * Mark credentials as selected so functions
150
+ * following authorize know which credentials
151
+ * to use if the message contained more than
152
+ * one
153
+ */
154
+int mark_authorized_cred(struct sip_msg* _m, struct hdr_field* _h)
155
+{
156
+	struct hdr_field* f;
157
+	
158
+	switch(_h->type) {
159
+	case HDR_AUTHORIZATION: f = _m->authorization; break;
160
+	case HDR_PROXYAUTH:     f = _m->proxy_auth;    break;
161
+	default:
162
+		LOG(L_ERR, "mark_authorized_cred(): Invalid header field type\n");
163
+		return -1;
164
+	}
165
+
166
+	if (!(f->parsed)) {
167
+		if (new_credentials(f) < 0) {
168
+			LOG(L_ERR, "mark_authorized_cred(): Error in new_credentials\n");
169
+			return -1;
170
+		}
171
+	}
172
+
173
+	((auth_body_t*)(f->parsed))->authorized = _h;
174
+
175
+	return 0;
176
+}
177
+
178
+
179
+/*
180
+ * Get pointer to authorized credentials, if there are no
181
+ * authorized credentials, 0 is returned
182
+ */
183
+int get_authorized_cred(struct hdr_field* _f, struct hdr_field** _h)
184
+{
185
+	if (_f && _f->parsed) {
186
+		*_h = ((auth_body_t*)(_f->parsed))->authorized;
187
+	} else {
188
+		*_h = 0;
189
+	}
190
+	
191
+	return 0;
192
+}
0 193
new file mode 100644
... ...
@@ -0,0 +1,92 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Digest credentials parser interface
5
+ */
6
+
7
+#ifndef DIGEST_H
8
+#define DIGEST_H
9
+
10
+#include "digest_parser.h"
11
+#include "../hf.h"         /* struct hdr_field */
12
+#include "../msg_parser.h"
13
+
14
+
15
+typedef struct auth_body {
16
+	     /* This is pointer to header field containing
17
+	      * parsed authorized digest credentials. This
18
+	      * pointer is set in sip_msg->{authorization,proxy_auth}
19
+	      * hooks if the authorized credentials are in another
20
+	      * header field (a SIP message may contain many digest
21
+	      * credentials with different realms).
22
+	      *
23
+	      * This is necessary for functions called after
24
+	      * {www,proxy}_authorize, these functions need to know
25
+	      * which credentials are authorized and they will simply
26
+	      * look into 
27
+	      * sip_msg->{authorization,proxy_auth}->parsed->authorized
28
+	      * If the pointer contains 0, then the hook itself contains
29
+	      * authorized credentials, otherwise they are in hdr_field
30
+	      * the pointer points to.
31
+	      */
32
+	struct hdr_field* authorized;
33
+	dig_cred_t digest;           /* Parsed digest credentials */
34
+	unsigned char stale;         /* Flag is set if nonce is stale */
35
+	int nonce_retries;           /* How many times the nonce was used */
36
+} auth_body_t;
37
+
38
+
39
+/*
40
+ * Errors returned by check_dig_cred
41
+ */
42
+typedef enum dig_err {
43
+	E_DIG_OK = 0,        /* Everything is OK */
44
+	E_DIG_USERNAME  = 1, /* Username missing */
45
+	E_DIG_REALM = 2,     /* Realm missing */
46
+	E_DIG_NONCE = 4,     /* Nonce value missing */
47
+	E_DIG_URI = 8,       /* URI missing */
48
+	E_DIG_RESPONSE = 16, /* Response missing */
49
+	E_DIG_CNONCE = 32,   /* CNONCE missing */
50
+	E_DIG_NC = 64,       /* Nonce-count missing */
51
+} dig_err_t;
52
+
53
+
54
+/*
55
+ * Parse digest credentials
56
+ */
57
+int parse_credentials(struct hdr_field* _h);
58
+
59
+
60
+/*
61
+ * Free all memory associated with parsed
62
+ * structures
63
+ */
64
+void free_credentials(auth_body_t** _b);
65
+
66
+
67
+/*
68
+ * Print dig_cred structure to stdout
69
+ */
70
+void print_cred(dig_cred_t* _c);
71
+
72
+
73
+/*
74
+ * Mark credentials as authorized
75
+ */
76
+int mark_authorized_cred(struct sip_msg* _m, struct hdr_field* _h);
77
+
78
+
79
+/*
80
+ * Get pointer to authorized credentials
81
+ */
82
+int get_authorized_cred(struct hdr_field* _f, struct hdr_field** _h);
83
+
84
+
85
+/*
86
+ * Check if credentials are correct
87
+ * (check of semantics)
88
+ */
89
+dig_err_t check_dig_cred(dig_cred_t* _c);
90
+
91
+
92
+#endif /* DIGEST_H */
0 93
new file mode 100644
... ...
@@ -0,0 +1,182 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * This file is automatically generated, do not edit
5
+ */
6
+
7
+#ifndef DIGEST_KEYS_H
8
+#define DIGEST_KEYS_H
9
+
10
+
11
+#define _user_ 0x72657375   /* "user" */
12
+#define _useR_ 0x52657375   /* "useR" */
13
+#define _usEr_ 0x72457375   /* "usEr" */
14
+#define _usER_ 0x52457375   /* "usER" */
15
+#define _uSer_ 0x72655375   /* "uSer" */
16
+#define _uSeR_ 0x52655375   /* "uSeR" */
17
+#define _uSEr_ 0x72455375   /* "uSEr" */
18
+#define _uSER_ 0x52455375   /* "uSER" */
19
+#define _User_ 0x72657355   /* "User" */
20
+#define _UseR_ 0x52657355   /* "UseR" */
21
+#define _UsEr_ 0x72457355   /* "UsEr" */
22
+#define _UsER_ 0x52457355   /* "UsER" */
23
+#define _USer_ 0x72655355   /* "USer" */
24
+#define _USeR_ 0x52655355   /* "USeR" */
25
+#define _USEr_ 0x72455355   /* "USEr" */
26
+#define _USER_ 0x52455355   /* "USER" */
27
+
28
+#define _name_ 0x656d616e   /* "name" */
29
+#define _namE_ 0x456d616e   /* "namE" */
30
+#define _naMe_ 0x654d616e   /* "naMe" */
31
+#define _naME_ 0x454d616e   /* "naME" */
32
+#define _nAme_ 0x656d416e   /* "nAme" */
33
+#define _nAmE_ 0x456d416e   /* "nAmE" */
34
+#define _nAMe_ 0x654d416e   /* "nAMe" */
35
+#define _nAME_ 0x454d416e   /* "nAME" */
36
+#define _Name_ 0x656d614e   /* "Name" */
37
+#define _NamE_ 0x456d614e   /* "NamE" */
38
+#define _NaMe_ 0x654d614e   /* "NaMe" */
39
+#define _NaME_ 0x454d614e   /* "NaME" */
40
+#define _NAme_ 0x656d414e   /* "NAme" */
41
+#define _NAmE_ 0x456d414e   /* "NAmE" */
42
+#define _NAMe_ 0x654d414e   /* "NAMe" */
43
+#define _NAME_ 0x454d414e   /* "NAME" */
44
+
45
+#define _real_ 0x6c616572   /* "real" */
46
+#define _reaL_ 0x4c616572   /* "reaL" */
47
+#define _reAl_ 0x6c416572   /* "reAl" */
48
+#define _reAL_ 0x4c416572   /* "reAL" */
49
+#define _rEal_ 0x6c614572   /* "rEal" */
50
+#define _rEaL_ 0x4c614572   /* "rEaL" */
51
+#define _rEAl_ 0x6c414572   /* "rEAl" */
52
+#define _rEAL_ 0x4c414572   /* "rEAL" */
53
+#define _Real_ 0x6c616552   /* "Real" */
54
+#define _ReaL_ 0x4c616552   /* "ReaL" */
55
+#define _ReAl_ 0x6c416552   /* "ReAl" */
56
+#define _ReAL_ 0x4c416552   /* "ReAL" */
57
+#define _REal_ 0x6c614552   /* "REal" */
58
+#define _REaL_ 0x4c614552   /* "REaL" */
59
+#define _REAl_ 0x6c414552   /* "REAl" */
60
+#define _REAL_ 0x4c414552   /* "REAL" */
61
+
62
+#define _nonc_ 0x636e6f6e   /* "nonc" */
63
+#define _nonC_ 0x436e6f6e   /* "nonC" */
64
+#define _noNc_ 0x634e6f6e   /* "noNc" */
65
+#define _noNC_ 0x434e6f6e   /* "noNC" */
66
+#define _nOnc_ 0x636e4f6e   /* "nOnc" */
67
+#define _nOnC_ 0x436e4f6e   /* "nOnC" */
68
+#define _nONc_ 0x634e4f6e   /* "nONc" */
69
+#define _nONC_ 0x434e4f6e   /* "nONC" */
70
+#define _Nonc_ 0x636e6f4e   /* "Nonc" */
71
+#define _NonC_ 0x436e6f4e   /* "NonC" */
72
+#define _NoNc_ 0x634e6f4e   /* "NoNc" */
73
+#define _NoNC_ 0x434e6f4e   /* "NoNC" */
74
+#define _NOnc_ 0x636e4f4e   /* "NOnc" */
75
+#define _NOnC_ 0x436e4f4e   /* "NOnC" */
76
+#define _NONc_ 0x634e4f4e   /* "NONc" */
77
+#define _NONC_ 0x434e4f4e   /* "NONC" */
78
+
79
+#define _resp_ 0x70736572   /* "resp" */
80
+#define _resP_ 0x50736572   /* "resP" */
81
+#define _reSp_ 0x70536572   /* "reSp" */
82
+#define _reSP_ 0x50536572   /* "reSP" */
83
+#define _rEsp_ 0x70734572   /* "rEsp" */
84
+#define _rEsP_ 0x50734572   /* "rEsP" */
85
+#define _rESp_ 0x70534572   /* "rESp" */
86
+#define _rESP_ 0x50534572   /* "rESP" */
87
+#define _Resp_ 0x70736552   /* "Resp" */
88
+#define _ResP_ 0x50736552   /* "ResP" */
89
+#define _ReSp_ 0x70536552   /* "ReSp" */
90
+#define _ReSP_ 0x50536552   /* "ReSP" */
91
+#define _REsp_ 0x70734552   /* "REsp" */
92
+#define _REsP_ 0x50734552   /* "REsP" */
93
+#define _RESp_ 0x70534552   /* "RESp" */
94
+#define _RESP_ 0x50534552   /* "RESP" */
95
+
96
+#define _onse_ 0x65736e6f   /* "onse" */
97
+#define _onsE_ 0x45736e6f   /* "onsE" */
98
+#define _onSe_ 0x65536e6f   /* "onSe" */
99
+#define _onSE_ 0x45536e6f   /* "onSE" */
100
+#define _oNse_ 0x65734e6f   /* "oNse" */
101
+#define _oNsE_ 0x45734e6f   /* "oNsE" */
102
+#define _oNSe_ 0x65534e6f   /* "oNSe" */
103
+#define _oNSE_ 0x45534e6f   /* "oNSE" */
104
+#define _Onse_ 0x65736e4f   /* "Onse" */
105
+#define _OnsE_ 0x45736e4f   /* "OnsE" */
106
+#define _OnSe_ 0x65536e4f   /* "OnSe" */
107
+#define _OnSE_ 0x45536e4f   /* "OnSE" */
108
+#define _ONse_ 0x65734e4f   /* "ONse" */
109
+#define _ONsE_ 0x45734e4f   /* "ONsE" */
110
+#define _ONSe_ 0x65534e4f   /* "ONSe" */
111
+#define _ONSE_ 0x45534e4f   /* "ONSE" */
112
+
113
+#define _cnon_ 0x6e6f6e63   /* "cnon" */
114
+#define _cnoN_ 0x4e6f6e63   /* "cnoN" */
115
+#define _cnOn_ 0x6e4f6e63   /* "cnOn" */
116
+#define _cnON_ 0x4e4f6e63   /* "cnON" */
117
+#define _cNon_ 0x6e6f4e63   /* "cNon" */
118
+#define _cNoN_ 0x4e6f4e63   /* "cNoN" */
119
+#define _cNOn_ 0x6e4f4e63   /* "cNOn" */
120
+#define _cNON_ 0x4e4f4e63   /* "cNON" */
121
+#define _Cnon_ 0x6e6f6e43   /* "Cnon" */
122
+#define _CnoN_ 0x4e6f6e43   /* "CnoN" */
123
+#define _CnOn_ 0x6e4f6e43   /* "CnOn" */
124
+#define _CnON_ 0x4e4f6e43   /* "CnON" */
125
+#define _CNon_ 0x6e6f4e43   /* "CNon" */
126
+#define _CNoN_ 0x4e6f4e43   /* "CNoN" */
127
+#define _CNOn_ 0x6e4f4e43   /* "CNOn" */
128
+#define _CNON_ 0x4e4f4e43   /* "CNON" */
129
+
130
+#define _opaq_ 0x7161706f   /* "opaq" */
131
+#define _opaQ_ 0x5161706f   /* "opaQ" */
132
+#define _opAq_ 0x7141706f   /* "opAq" */
133
+#define _opAQ_ 0x5141706f   /* "opAQ" */
134
+#define _oPaq_ 0x7161506f   /* "oPaq" */
135
+#define _oPaQ_ 0x5161506f   /* "oPaQ" */
136
+#define _oPAq_ 0x7141506f   /* "oPAq" */
137
+#define _oPAQ_ 0x5141506f   /* "oPAQ" */
138
+#define _Opaq_ 0x7161704f   /* "Opaq" */
139
+#define _OpaQ_ 0x5161704f   /* "OpaQ" */
140
+#define _OpAq_ 0x7141704f   /* "OpAq" */
141
+#define _OpAQ_ 0x5141704f   /* "OpAQ" */
142
+#define _OPaq_ 0x7161504f   /* "OPaq" */
143
+#define _OPaQ_ 0x5161504f   /* "OPaQ" */
144
+#define _OPAq_ 0x7141504f   /* "OPAq" */
145
+#define _OPAQ_ 0x5141504f   /* "OPAQ" */
146
+
147
+#define _algo_ 0x6f676c61   /* "algo" */
148
+#define _algO_ 0x4f676c61   /* "algO" */
149
+#define _alGo_ 0x6f476c61   /* "alGo" */
150
+#define _alGO_ 0x4f476c61   /* "alGO" */
151
+#define _aLgo_ 0x6f674c61   /* "aLgo" */
152
+#define _aLgO_ 0x4f674c61   /* "aLgO" */
153
+#define _aLGo_ 0x6f474c61   /* "aLGo" */
154
+#define _aLGO_ 0x4f474c61   /* "aLGO" */
155
+#define _Algo_ 0x6f676c41   /* "Algo" */
156
+#define _AlgO_ 0x4f676c41   /* "AlgO" */
157
+#define _AlGo_ 0x6f476c41   /* "AlGo" */
158
+#define _AlGO_ 0x4f476c41   /* "AlGO" */
159
+#define _ALgo_ 0x6f674c41   /* "ALgo" */
160
+#define _ALgO_ 0x4f674c41   /* "ALgO" */
161
+#define _ALGo_ 0x6f474c41   /* "ALGo" */
162
+#define _ALGO_ 0x4f474c41   /* "ALGO" */
163
+
164
+#define _rith_ 0x68746972   /* "rith" */
165
+#define _ritH_ 0x48746972   /* "ritH" */
166
+#define _riTh_ 0x68546972   /* "riTh" */
167
+#define _riTH_ 0x48546972   /* "riTH" */
168
+#define _rIth_ 0x68744972   /* "rIth" */
169
+#define _rItH_ 0x48744972   /* "rItH" */
170
+#define _rITh_ 0x68544972   /* "rITh" */
171
+#define _rITH_ 0x48544972   /* "rITH" */
172
+#define _Rith_ 0x68746952   /* "Rith" */
173
+#define _RitH_ 0x48746952   /* "RitH" */
174
+#define _RiTh_ 0x68546952   /* "RiTh" */
175
+#define _RiTH_ 0x48546952   /* "RiTH" */
176
+#define _RIth_ 0x68744952   /* "RIth" */
177
+#define _RItH_ 0x48744952   /* "RItH" */
178
+#define _RITh_ 0x68544952   /* "RITh" */
179
+#define _RITH_ 0x48544952   /* "RITH" */
180
+
181
+
182
+#endif /* DIGEST_KEYS_H */
0 183
new file mode 100644
... ...
@@ -0,0 +1,343 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Digest credentials parser
5
+ */
6
+
7
+
8
+#include "digest_parser.h"
9
+#include "../../trim.h"    /* trim_leading */
10
+#include <string.h>        /* strncasecmp */
11
+#include "param_parser.h"  /* Digest parameter name parser */
12
+#include "../../ut.h"      /* q_memchr */
13
+
14
+
15
+#define DIGEST_SCHEME "digest"
16
+#define DIG_LEN 6
17
+
18
+#define QOP_AUTH_STR "auth"
19
+#define QOP_AUTHINT_STR "auth-int"
20
+
21
+#define ALG_MD5_STR "MD5"
22
+#define ALG_MD5SESS_STR "MD5-sess"
23
+
24
+
25
+static inline int parse_quoted(str* _s, str* _r);
26
+static inline int parse_token(str* _s, str* _r);
27
+static inline int parse_digest_param(str* _s, dig_cred_t* _c);
28
+static inline int parse_digest_params(str* _s, dig_cred_t* _c);
29
+static int parse_qop(struct qp* _q);
30
+static int parse_algorithm(struct algorithm* _a);
31
+
32
+
33
+/*
34
+ * Parse quoted string in a parameter body
35
+ * return the string without quotes in _r
36
+ * parameter and update _s to point behind the
37
+ * closing quote
38
+ */
39
+static inline int parse_quoted(str* _s, str* _r)
40
+{
41
+	char* end_quote;
42
+
43
+	     /* The string must have at least
44
+	      * surrounding quotes
45
+	      */
46
+	if (_s->len < 2) {
47
+		return -1;
48
+	}
49
+
50
+	     /* Skip opening quote */
51
+	_s->s++;
52
+	_s->len--;
53
+
54
+
55
+	     /* Find closing quote */
56
+	end_quote = q_memchr(_s->s, '\"', _s->len);
57
+
58
+	     /* Not found, return error */
59
+	if (!end_quote) {
60
+		return -2;
61
+	}
62
+
63
+	     /* Let _r point to the string without
64
+	      * surrounding quotes
65
+	      */
66
+	_r->s = _s->s;
67
+	_r->len = end_quote - _s->s;
68
+
69
+	     /* Update _s parameter to point
70
+	      * behind the closing quote
71
+	      */
72
+	_s->len -= (end_quote - _s->s + 1);
73
+	_s->s = end_quote + 1;
74
+
75
+	     /* Everything went OK */
76
+	return 0;
77
+}
78
+
79
+
80
+/*
81
+ * Parse unquoted token in a parameter body
82
+ * let _r point to the token and update _s
83
+ * to point right behind the token
84
+ */
85
+static inline int parse_token(str* _s, str* _r)
86
+{
87
+	int i;
88
+
89
+	     /* There is nothing to parse,
90
+	      * return error
91
+	      */
92
+	if (_s->len == 0) {
93
+		return -1;
94
+	}
95
+
96
+	     /* Save the begining of the
97
+	      * token in _r->s
98
+	      */
99
+	_r->s = _s->s;
100
+
101
+	     /* Iterate throught the
102
+	      * token body
103
+	      */
104
+	for(i = 0; i < _s->len; i++) {
105
+
106
+		     /* All these characters
107
+		      * mark end of the token
108
+		      */
109
+		switch(_s->s[i]) {
110
+		case ' ':
111
+		case '\t':
112
+		case '\r':
113
+		case '\n':
114
+		case ',':
115
+			     /* So if you find
116
+			      * any of them
117
+			      * stop iterating
118
+			      */
119
+			goto out;
120
+		}
121
+	}
122
+ out:
123
+	     /* Save length of the token */
124
+        _r->len = i;
125
+
126
+	     /* Update _s parameter so it points
127
+	      * right behind the end of the token
128
+	      */
129
+	_s->s = _s->s + i;
130
+	_s->len -= i;
131
+
132
+	     /* Everyting went OK */
133
+	return 0;
134
+}
135
+
136
+
137
+/*
138
+ * Parse a digest parameter
139
+ */
140
+static inline int parse_digest_param(str* _s, dig_cred_t* _c)
141
+{
142
+	dig_par_t t;
143
+	str* ptr;
144
+	str dummy;
145
+
146
+	     /* Get type of the parameter */
147
+	if (parse_param_name(_s, &t) < 0) {
148
+		return -1;
149
+	}
150
+
151
+	_s->s++;  /* skip = */
152
+	_s->len--;
153
+
154
+	     /* Find the begining of body */
155
+	trim_leading(_s);
156
+
157
+	if (_s->len == 0) {
158
+		return -2;
159
+	}
160
+
161
+	     /* Decide in which attribute the
162
+	      * body content will be stored
163
+	      */
164
+	switch(t) {
165
+	case PAR_USERNAME:  ptr = &(_c->username);    break;
166
+	case PAR_REALM:     ptr = &(_c->realm);       break;
167
+	case PAR_NONCE:     ptr = &(_c->nonce);       break;
168
+	case PAR_URI:       ptr = &(_c->uri);         break;
169
+	case PAR_RESPONSE:  ptr = &(_c->response);    break;
170
+	case PAR_CNONCE:    ptr = &(_c->cnonce);      break;
171
+	case PAR_OPAQUE:    ptr = &(_c->opaque);      break;
172
+	case PAR_QOP:       ptr = &(_c->qop.qop_str); break;
173
+	case PAR_NC:        ptr = &(_c->nc);          break;
174
+	case PAR_ALGORITHM: ptr = &(_c->alg.alg_str); break;
175
+	case PAR_OTHER:     ptr = &dummy;             break;
176
+	default:            ptr = &dummy;             break;
177
+	}
178
+
179
+	     /* If the first character is qoute, it is
180
+	      * a quoted string, otherwise it is a token
181
+	      */
182
+	if (*(_s->s) == '\"') {
183
+		if (parse_quoted(_s, ptr) < 0) {
184
+			return -3;
185
+		}
186
+	} else {
187
+		if (parse_token(_s, ptr) < 0) {
188
+			return -4;
189
+		}
190
+	}
191
+	
192
+	return 0;
193
+}
194
+
195
+
196
+
197
+/*
198
+ * Parse Digest credentials parameter, one by one
199
+ */
200
+static inline int parse_digest_params(str* _s, dig_cred_t* _c)
201
+{
202
+	char* comma;
203
+
204
+	do {
205
+		     /* Parse the first parameter */
206
+		if (parse_digest_param(_s, _c) < 0) {
207
+			return -1;
208
+		}
209
+		
210
+		     /* Try to find the next parameter */
211
+		comma = q_memchr(_s->s, ',', _s->len);
212
+		if (comma) {
213
+			     /* Yes, there is another, 
214
+			      * remove any leading whitespaces
215
+			      * and let _s point to the next
216
+			      * parameter name
217
+			      */
218
+			_s->len -= comma - _s->s + 1;
219
+			_s->s = comma + 1;
220
+			trim_leading(_s);
221
+		}
222
+	} while(comma); /* Repeat while there are next parameters */
223
+
224
+	     /* Parse QOP body if the parameter was present */
225
+	if (_c->qop.qop_str.s != 0) {
226
+		if (parse_qop(&(_c->qop)) < 0) {
227
+			return -5;
228
+		}
229
+	}
230
+
231
+	     /* Parse algorithm body if the parameter was present */
232
+	if (_c->alg.alg_str.s != 0) {
233
+		if (parse_algorithm(&(_c->alg)) < 0) {
234
+			return -6;
235
+		}
236
+	}
237
+
238
+	return 0;
239
+}
240
+
241
+
242
+/*
243
+ * Parse qop parameter body
244
+ */
245
+static int parse_qop(struct qp* _q)
246
+{
247
+	if (!strncasecmp(_q->qop_str.s, QOP_AUTH_STR, _q->qop_str.len)) {
248
+		_q->qop_parsed = QOP_AUTH;
249
+	} else if (!strncasecmp(_q->qop_str.s, QOP_AUTHINT_STR, _q->qop_str.len)) {
250
+		_q->qop_parsed = QOP_AUTHINT;
251
+	} else {
252
+		_q->qop_parsed = QOP_OTHER;
253
+	}
254
+	
255
+	return 0;
256
+}
257
+
258
+
259
+/*
260
+ * Parse algorithm parameter body
261
+ */
262
+static int parse_algorithm(struct algorithm* _a)
263
+{
264
+	if (!strncasecmp(_a->alg_str.s, ALG_MD5_STR, _a->alg_str.len)) {
265
+		_a->alg_parsed = ALG_MD5;
266
+	} else if (!strncasecmp(_a->alg_str.s, ALG_MD5SESS_STR, _a->alg_str.len)) {
267
+		_a->alg_parsed = ALG_MD5SESS;
268
+	} else {
269
+		_a->alg_parsed = ALG_OTHER;
270
+	}
271
+
272
+	return 0;
273
+}
274
+
275
+
276
+/*
277
+ * We support Digest authentication only
278
+ *
279
+ * Returns:
280
+ *  0 - if everything is OK
281
+ * -1 - Error while parsing
282
+ *  1 - Unknown scheme
283
+ */
284
+int parse_digest_cred(str* _s, dig_cred_t* _c)
285
+{
286
+	str tmp;
287
+
288
+	     /* Make a temporary copy, we are
289
+	      * gonna to modify it 
290
+	      */
291
+	tmp.s = _s->s;
292
+	tmp.len = _s->len;
293
+
294
+	     /* Remove any leading spaces, tabs, \r and \n */
295
+	trim_leading(&tmp);
296
+
297
+	     /* Check the string length */
298
+	if (tmp.len < (DIG_LEN + 1)) return 1; /* Too short, unknown scheme */
299
+
300
+	     /* Now test, if it is digest scheme, since it is the only
301
+	      * scheme we are able to parse here
302
+	      */
303
+	if (!strncasecmp(tmp.s, DIGEST_SCHEME, DIG_LEN) &&
304
+	    ((tmp.s[DIG_LEN] == ' ') ||     /* Test for one of LWS chars */
305
+	     (tmp.s[DIG_LEN] == '\r') || 
306
+	     (tmp.s[DIG_LEN] == 'n') || 
307
+	     (tmp.s[DIG_LEN] == '\t'))) {
308
+		     /* Scheme is Digest */
309
+		tmp.s += DIG_LEN + 1;
310
+		tmp.len -= DIG_LEN + 1;
311
+		
312
+		     /* Again, skip all whitespaces */
313
+		trim_leading(&tmp);
314
+
315
+		     /* And parse digest parameters */
316
+		if (parse_digest_params(&tmp, _c) < 0) {
317
+			return -1;
318
+		} else {
319
+			return 0;
320
+		}
321
+	} else {
322
+		return 1; /* Unknown scheme */
323
+	}
324
+}
325
+
326
+
327
+/*
328
+ * Initialize a digest credentials structure
329
+ */
330
+void init_dig_cred(dig_cred_t* _c)
331
+{
332
+	memset(_c, 0, sizeof(dig_cred_t));
333
+}
334
+
335
+
336
+/*
337
+ * Initialize digest_parser
338
+ */
339
+ 
340
+void init_digest_parser(void)
341
+{
342
+        init_digest_htable();
343
+}
0 344
new file mode 100644
... ...
@@ -0,0 +1,87 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Digest credentials parser
5
+ */
6
+
7
+
8
+#ifndef DIGEST_PARSER_H
9
+#define DIGEST_PARSER_H
10
+
11
+#include "../../str.h"
12
+
13
+
14
+/* Type of algorithm used */
15
+typedef enum alg {
16
+	ALG_UNSPEC = 0,   /* Algorithm parameter not specified */
17
+	ALG_MD5 = 1,      /* MD5 - default value*/
18
+	ALG_MD5SESS = 2,  /* MD5-Session */
19
+	ALG_OTHER = 4     /* Unknown */
20
+} alg_t;
21
+
22
+
23
+/* Quality Of Protection used */
24
+typedef enum qop_type { 
25
+	QOP_UNSPEC = 0,   /* QOP parameter not present in response */
26
+	QOP_AUTH = 1,     /* Authentication only */
27
+	QOP_AUTHINT = 2,  /* Authentication with integrity checks */
28
+	QOP_OTHER = 4     /* Unknown */
29
+} qop_type_t;
30
+
31
+
32
+/* Algorithm structure */
33
+struct algorithm {
34
+	str alg_str;       /* The original string representation */
35
+	alg_t alg_parsed;  /* Parsed value */
36
+};
37
+
38
+
39
+/* QOP structure */
40
+struct qp {
41
+	str qop_str;           /* The original string representation */
42
+	qop_type_t qop_parsed; /* Parsed value */
43
+};
44
+
45
+
46
+/*
47
+ * Parsed digest credentials
48
+ */
49
+typedef struct dig_cred {
50
+	str username;         /* Username */
51
+	str realm;            /* Realm */
52
+	str nonce;            /* Nonce value */
53
+	str uri;              /* URI */
54
+	str response;         /* Response string */
55
+	str algorithm;        /* Algorithm in string representation */
56
+	struct algorithm alg; /* Type of algorithm used */
57
+	str cnonce;           /* Cnonce value */
58
+	str opaque;           /* Opaque data string */
59
+	struct qp qop;        /* Quality Of Protection */
60
+	str nc;               /* Nonce count parameter */
61
+} dig_cred_t;
62
+
63
+
64
+/*
65
+ * Initialize digest parser
66
+ */
67
+void init_digest_parser(void);
68
+
69
+
70
+/*
71
+ * Initialize a digest credentials structure
72
+ */
73
+void init_dig_cred(dig_cred_t* _c);
74
+
75
+
76
+/*
77
+ * We support Digest authentication only
78
+ *
79
+ * Returns:
80
+ *  0 - if everything is OK
81
+ * -1 - Error while parsing
82
+ *  1 - Unknown scheme
83
+ */
84
+int parse_digest_cred(str* _s, dig_cred_t* _c);
85
+
86
+
87
+#endif /* DIGEST_PARSER_H */
0 88
new file mode 100644
... ...
@@ -0,0 +1,361 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * 32-bit Digest parameter name parser
5
+ */
6
+
7
+
8
+#include "param_parser.h"
9
+#include "digest_keys.h"
10
+#include "../../trim.h"
11
+#include "../../ut.h"
12
+
13
+/*
14
+ * Precalculated hash table size
15
+ * WARNING: The size MUST be recalculated
16
+ *          again if new parameter names
17
+ *          should be parsed
18
+ */
19
+#define HASH_TABLE_SIZE 859
20
+
21
+
22
+/*
23
+ * Hash function
24
+ */
25
+#define HASH_FUNC(val) ((val) % HASH_TABLE_SIZE)
26
+
27
+
28
+/*
29
+ * This constant marks an empty hash table element
30
+ */
31
+#define HASH_EMPTY 0x2d2d2d2d
32
+
33
+
34
+/*
35
+ * Hash table entry
36
+ */
37
+struct ht_entry {
38
+	unsigned int key;
39
+	unsigned int value;
40
+};
41
+
42
+
43
+static struct ht_entry hash_table[HASH_TABLE_SIZE];
44
+
45
+
46
+/*
47
+ * Pointer to the hash table
48
+ */
49
+/*
50
+static struct ht_entry *hash_table;
51
+*/
52
+
53
+
54
+/*
55
+ * Declarations
56
+ */
57
+static void set_entry (unsigned int key, unsigned int val);
58
+static inline int unify (int key);
59
+
60
+
61
+
62
+/*
63
+ * Used to initialize hash table
64
+ */
65
+static void set_entry(unsigned int key, unsigned int val)
66
+{
67
+	hash_table[HASH_FUNC(key)].key = key;
68
+	hash_table[HASH_FUNC(key)].value = val;
69
+}
70
+
71
+
72
+static inline int unify(int key)
73
+{
74
+	register struct ht_entry* en;
75
+
76
+	en = &hash_table[HASH_FUNC(key)];
77
+	if (en->key == key) {
78
+		return en->value;
79
+	} else {
80
+		return key;
81
+	}
82
+}
83
+
84
+
85
+/*
86
+ * Parse short (less than 4 bytes) parameter names
87
+ */
88
+#define PARSE_SHORT                                                   \
89
+	switch(*p) {                                                  \
90
+	case 'u':                                                     \
91
+	case 'U':                                                     \
92
+		if ((*(p + 1) == 'r') || (*(p + 1) == 'R')) {         \
93
+			if ((*(p + 2) == 'i') || (*(p + 2) == 'I')) { \
94
+				*_type = PAR_URI;                     \
95
+                                p += 3;                               \
96
+				goto end;                             \
97
+			}                                             \
98
+		}                                                     \
99
+		break;                                                \
100
+                                                                      \
101
+	case 'q':                                                     \
102
+	case 'Q':                                                     \
103
+		if ((*(p + 1) == 'o') || (*(p + 1) == 'O')) {         \
104
+			if ((*(p + 2) == 'p') || (*(p + 2) == 'P')) { \
105
+				*_type = PAR_QOP;                     \
106
+                                p += 3;                               \
107
+				goto end;                             \
108
+			}                                             \
109
+		}                                                     \
110
+		break;                                                \
111
+                                                                      \
112
+	case 'n':                                                     \
113
+	case 'N':                                                     \
114
+		if ((*(p + 1) == 'c') || (*(p + 1) == 'C')) {         \
115
+			*_type = PAR_NC;                              \
116
+                        p += 2;                                       \
117
+			goto end;                                     \
118
+		}                                                     \
119
+		break;                                                \
120
+	}
121
+
122
+
123
+/*
124
+ * Read 4-bytes from memory and store them in an integer variable
125
+ * Reading byte by byte ensures, that the code works also on HW which
126
+ * does not allow reading 4-bytes at once from unaligned memory position
127
+ * (Sparc for example)
128
+ */
129
+#define READ(val) \
130
+(*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
131
+
132
+
133
+#define name_CASE                      \
134
+        switch(val) {                  \
135
+        case _name_:                   \
136
+		*_type = PAR_USERNAME; \
137
+                p += 4;                \
138
+		goto end;              \
139
+        }
140
+
141
+
142
+#define user_CASE         \
143
+        p += 4;           \
144
+        val = READ(p);    \
145
+        name_CASE;        \
146
+                          \
147
+        val = unify(val); \
148
+        name_CASE;        \
149
+        goto other;
150
+
151
+
152
+#define real_CASE                         \
153
+        p += 4;                           \
154
+        if ((*p == 'm') || (*p == 'M')) { \
155
+		*_type = PAR_REALM;       \
156
+                p++;                      \
157
+		goto end;                 \
158
+	}
159
+
160
+
161
+#define nonc_CASE                         \
162
+        p += 4;                           \
163
+        if ((*p == 'e') || (*p == 'E')) { \
164
+	        *_type = PAR_NONCE;       \
165
+                p++;                      \
166
+		goto end;                 \
167
+	}
168
+
169
+
170
+#define onse_CASE                      \
171
+        switch(val) {                  \
172
+        case _onse_:                   \
173
+		*_type = PAR_RESPONSE; \
174
+                p += 4;                \
175
+		goto end;              \
176
+        }
177
+
178
+
179
+#define resp_CASE         \
180
+        p += 4;           \
181
+        val = READ(p);    \
182
+        onse_CASE;        \
183
+                          \
184
+        val = unify(val); \
185
+        onse_CASE;        \
186
+        goto other;
187
+
188
+
189
+#define cnon_CASE                                 \
190
+        p += 4;                                   \
191
+        if ((*p == 'c') || (*p == 'C')) {         \
192
+		p++;                              \
193
+		if ((*p == 'e') || (*p == 'E')) { \
194
+			*_type = PAR_CNONCE;      \
195
+                        p++;                      \
196
+			goto end;                 \
197
+		}                                 \
198
+	}                                         \
199
+        goto other;
200
+
201
+
202
+#define opaq_CASE                                 \
203
+        p += 4;                                   \
204
+        if ((*p == 'u') || (*p == 'U')) {         \
205
+		p++;                              \
206
+		if ((*p == 'e') || (*p == 'E')) { \
207
+			*_type = PAR_OPAQUE;      \
208
+                        p++;                      \
209
+			goto end;                 \
210
+		}                                 \
211
+	}                                         \
212
+        goto other;
213
+
214
+
215
+#define rith_CASE                                 \
216
+        switch(val) {                             \
217
+	case _rith_:                              \
218
+		p += 4;                           \
219
+		if ((*p == 'm') || (*p == 'M')) { \
220
+			*_type = PAR_ALGORITHM;   \
221
+                        p++;                      \
222
+			goto end;                 \
223
+		}                                 \
224
+		goto other;                       \
225
+	}
226
+
227
+
228
+#define algo_CASE         \
229
+        p += 4;           \
230
+        val = READ(p);    \
231
+        rith_CASE;        \
232
+                          \
233
+        val = unify(val); \
234
+        rith_CASE;        \
235
+        goto other;
236
+
237
+
238
+#define FIRST_QUATERNIONS       \
239
+        case _user_: user_CASE; \
240
+        case _real_: real_CASE; \
241
+        case _nonc_: nonc_CASE; \
242
+        case _resp_: resp_CASE; \
243
+        case _cnon_: cnon_CASE; \
244
+        case _opaq_: opaq_CASE; \
245
+        case _algo_: algo_CASE;
246
+
247
+
248
+
249
+
250
+int parse_param_name(str* _s, dig_par_t* _type)
251
+{
252
+	register char* p;
253
+	register int val;
254
+	char* end;
255
+
256
+	end = _s->s + _s->len;
257
+
258
+	p = _s->s;
259
+	val = READ(p);
260
+
261
+	if (_s->len < 4) {
262
+		goto other;
263
+	}
264
+
265
+	switch(val) {
266
+	FIRST_QUATERNIONS;
267
+	default:
268
+		PARSE_SHORT;
269
+
270
+		val = unify(val);
271
+		switch(val) {
272
+		FIRST_QUATERNIONS;
273
+		default: goto other;
274
+		}
275
+        }
276
+
277
+ end:
278
+	_s->len -= p - _s->s;
279
+	_s->s = p;
280
+
281
+	trim_leading(_s);
282
+	if (_s->s[0] == '=') {
283
+		return 0;
284
+	}
285
+	
286
+ other:
287
+	p = q_memchr(p, '=', end - p);
288
+	if (!p) {
289
+		return -1; /* Parse error */
290
+	} else {
291
+		*_type = PAR_OTHER;
292
+		_s->len -= p - _s->s;
293
+		_s->s = p;
294
+		return 0;
295
+	}
296
+}
297
+
298
+
299
+/* Number of distinct keys */
300
+#define NUM_KEYS  160
301
+
302
+/* Number of distinct values */
303
+#define NUM_VALS 10
304
+
305
+
306
+/*
307
+ * Create synonym-less (precalculated) hash table
308
+ */
309
+void init_digest_htable(void)
310
+{
311
+	int i, j, k;
312
+
313
+	unsigned int init_val[NUM_VALS] = {
314
+		_user_, _name_, _real_, _nonc_,
315
+		_resp_, _onse_, _cnon_, _opaq_,
316
+		_algo_, _rith_
317
+	};
318
+
319
+	unsigned int key_nums[NUM_VALS] = {
320
+		16, 16, 16, 16, 16,
321
+		16, 16, 16, 16, 16
322
+	};
323
+	
324
+	unsigned int init_key[NUM_KEYS] = {
325
+		_user_, _useR_, _usEr_, _usER_, _uSer_, _uSeR_, _uSEr_, _uSER_, 
326
+		_User_, _UseR_, _UsEr_, _UsER_, _USer_, _USeR_, _USEr_, _USER_, 
327
+		_name_, _namE_, _naMe_, _naME_, _nAme_, _nAmE_, _nAMe_, _nAME_, 
328
+		_Name_, _NamE_, _NaMe_, _NaME_, _NAme_, _NAmE_, _NAMe_, _NAME_, 
329
+		_real_, _reaL_, _reAl_, _reAL_, _rEal_, _rEaL_, _rEAl_, _rEAL_, 
330
+		_Real_, _ReaL_, _ReAl_, _ReAL_, _REal_, _REaL_, _REAl_, _REAL_, 
331
+		_nonc_, _nonC_, _noNc_, _noNC_, _nOnc_, _nOnC_, _nONc_, _nONC_, 
332
+		_Nonc_, _NonC_, _NoNc_, _NoNC_, _NOnc_, _NOnC_, _NONc_, _NONC_, 
333
+		_resp_, _resP_, _reSp_, _reSP_, _rEsp_, _rEsP_, _rESp_, _rESP_, 
334
+		_Resp_, _ResP_, _ReSp_, _ReSP_, _REsp_, _REsP_, _RESp_, _RESP_, 
335
+		_onse_, _onsE_, _onSe_, _onSE_, _oNse_, _oNsE_, _oNSe_, _oNSE_, 
336
+		_Onse_, _OnsE_, _OnSe_, _OnSE_, _ONse_, _ONsE_, _ONSe_, _ONSE_, 
337
+		_cnon_, _cnoN_, _cnOn_, _cnON_, _cNon_, _cNoN_, _cNOn_, _cNON_, 
338
+		_Cnon_, _CnoN_, _CnOn_, _CnON_, _CNon_, _CNoN_, _CNOn_, _CNON_, 
339
+		_opaq_, _opaQ_, _opAq_, _opAQ_, _oPaq_, _oPaQ_, _oPAq_, _oPAQ_, 
340
+		_Opaq_, _OpaQ_, _OpAq_, _OpAQ_, _OPaq_, _OPaQ_, _OPAq_, _OPAQ_, 
341
+		_algo_, _algO_, _alGo_, _alGO_, _aLgo_, _aLgO_, _aLGo_, _aLGO_, 
342
+		_Algo_, _AlgO_, _AlGo_, _AlGO_, _ALgo_, _ALgO_, _ALGo_, _ALGO_, 
343
+		_rith_, _ritH_, _riTh_, _riTH_, _rIth_, _rItH_, _rITh_, _rITH_, 
344
+		_Rith_, _RitH_, _RiTh_, _RiTH_, _RIth_, _RItH_, _RITh_, _RITH_
345
+	};
346
+
347
+
348
+	     /* Mark all elements as empty */
349
+	for(i = 0; i < HASH_TABLE_SIZE; i++) {
350
+		set_entry(HASH_EMPTY, HASH_EMPTY);
351
+	}
352
+
353
+	k = 0;
354
+
355
+	     /* Initialize hash table content */
356
+	for(i = 0; i < NUM_VALS; i++) {
357
+		for(j = 0; j < key_nums[i]; j++) {
358
+			set_entry(init_key[k++], init_val[i]);
359
+		}
360
+	}
361
+}
0 362
new file mode 100644
... ...
@@ -0,0 +1,43 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * 32-bit Digest parameter name parser
5
+ */
6
+
7
+#ifndef PARAM_PARSER_H
8
+#define PARAM_PARSER_H
9
+
10
+#include "../../str.h"
11
+
12
+
13
+/*
14
+ * Digest parameter types
15
+ */
16
+typedef enum dig_par {
17
+	PAR_USERNAME,  /* username parameter */
18
+	PAR_REALM,     /* realm parameter */
19
+	PAR_NONCE,     /* nonce parameter */
20
+	PAR_URI,       /* uri parameter */
21
+	PAR_RESPONSE,  /* response parameter */
22
+	PAR_CNONCE,    /* cnonce parameter */
23
+	PAR_OPAQUE,    /* opaque parameter */
24
+	PAR_QOP,       /* qop parameter */
25
+	PAR_NC,        /* nonce-count parameter */
26
+	PAR_ALGORITHM, /* algorithm parameter */
27
+	PAR_OTHER      /* unknown parameter */
28
+} dig_par_t;
29
+
30
+
31
+/*
32
+ * Parse digest parameter name
33
+ */
34
+int parse_param_name(str* _s, dig_par_t* _type);
35
+
36
+
37
+/*
38
+ * Initialize hash table
39
+ */
40
+void init_digest_htable(void);
41
+
42
+
43
+#endif /* PARAM_PARSER_H */