1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
diff -Naur cyrus-sasl-2.1.18-orig/plugins/digestmd5.c cyrus-sasl-2.1.18/plugins/digestmd5.c
--- cyrus-sasl-2.1.18-orig/plugins/digestmd5.c 2004-02-23 17:03:09.000000000 -0500
+++ cyrus-sasl-2.1.18/plugins/digestmd5.c 2004-07-06 22:08:23.159206640 -0400
@@ -151,6 +151,10 @@
#define SP (32)
#define DEL (127)
+#define NEED_ESCAPING "\"\\"
+
+static char *quote (char *str);
+
struct context;
/* function definitions for cipher encode/decode */
@@ -498,21 +502,42 @@
ret = _plug_buf_alloc(utils, str, buflen,
*curlen + 1 + namesize + 2 + valuesize + 2);
if(ret != SASL_OK) return ret;
-
- *curlen = *curlen + 1 + namesize + 2 + valuesize + 2;
-
+
+ if (*curlen > 0) {
strcat(*str, ",");
strcat(*str, name);
-
+ } else {
+ strcpy(*str, name);
+ }
+
if (need_quotes) {
- strcat(*str, "=\"");
- strcat(*str, (char *) value); /* XXX. What about quoting??? */
- strcat(*str, "\"");
- } else {
- strcat(*str, "=");
- strcat(*str, (char *) value);
- }
-
+ strcat(*str, "=\"");
+
+ /* Check if the value needs quoting */
+ if (strpbrk ((char *)value, NEED_ESCAPING) != NULL) {
+ char * quoted = quote ((char *) value);
+ valuesize = strlen(quoted);
+ /* As the quoted string is bigger, make sure we have enough
+ space now */
+ ret = _plug_buf_alloc(utils, str, buflen,
+ *curlen + 1 + namesize + 2 + valuesize + 2);
+ if (ret == SASL_OK) {
+ strcat(*str, quoted);
+ free (quoted);
+ } else {
+ free (quoted);
+ return ret;
+ }
+ } else {
+ strcat(*str, (char *) value);
+ }
+ strcat(*str, "\"");
+ } else {
+ strcat(*str, "=");
+ strcat(*str, (char *) value);
+ }
+
+ *curlen = *curlen + 1 + namesize + 2 + valuesize + 2;
return SASL_OK;
}
@@ -622,7 +647,8 @@
}
/* NULL - error (unbalanced quotes),
- otherwise pointer to the first character after value */
+ otherwise pointer to the first character after value
+ The function performs work in place. */
static char *unquote (char *qstr)
{
char *endvalue;
@@ -663,12 +689,49 @@
endvalue++;
}
else { /* not qouted value (token) */
+ /* qstr already contains output */
endvalue = skip_token(qstr,0);
};
return endvalue;
}
+/* Unlike unquote, this function returns an allocated quoted copy */
+static char *quote (char *str)
+{
+ char *p;
+ char *outp;
+ char *result;
+ int num_to_escape; /* How many characters need escaping */
+
+ if (!str) return NULL;
+
+ num_to_escape = 0;
+ p = strpbrk (str, NEED_ESCAPING);
+ while (p != NULL) {
+ num_to_escape++;
+ p = strpbrk (p + 1, NEED_ESCAPING);
+ }
+
+ if (num_to_escape == 0) {
+ return (strdup (str));
+ }
+
+ result = malloc (strlen(str) + num_to_escape + 1);
+ for (p = str, outp = result; *p; p++) {
+ if (*p == '"' || *p == '\\') {
+ *outp = '\\';
+ outp++;
+ }
+ *outp = *p;
+ outp++;
+ }
+
+ *outp = '\0';
+
+ return (result);
+}
+
static void get_pair(char **in, char **name, char **value)
{
char *endpair;
@@ -1791,12 +1854,16 @@
return SASL_FAIL;
}
- resplen = strlen(nonce) + strlen("nonce") + 5;
- result = _plug_buf_alloc(sparams->utils, &(text->out_buf),
- &(text->out_buf_len), resplen);
- if(result != SASL_OK) return result;
-
- sprintf(text->out_buf, "nonce=\"%s\"", nonce);
+ resplen = 0;
+ text->out_buf = NULL;
+ text->out_buf_len = 0;
+ if (add_to_challenge(sparams->utils,
+ &text->out_buf, &text->out_buf_len, &resplen,
+ "nonce", (unsigned char *) nonce,
+ TRUE) != SASL_OK) {
+ SETERROR(sparams->utils, "internal error: add_to_challenge failed");
+ return SASL_FAIL;
+ }
/* add to challenge; if we chose not to specify a realm, we won't
* send one to the client */
@@ -2830,7 +2897,7 @@
char maxbufstr[64];
char *response = NULL;
unsigned resplen = 0;
- int result;
+ int result = SASL_OK;
switch (ctext->protection) {
case DIGEST_PRIVACY:
@@ -2892,13 +2959,16 @@
&text->response_value);
- resplen = strlen(oparams->authid) + strlen("username") + 5;
- result =_plug_buf_alloc(params->utils, &(text->out_buf),
- &(text->out_buf_len),
- resplen);
- if (result != SASL_OK) goto FreeAllocatedMem;
-
- sprintf(text->out_buf, "username=\"%s\"", oparams->authid);
+ resplen = 0;
+ text->out_buf = NULL;
+ text->out_buf_len = 0;
+ if (add_to_challenge(params->utils,
+ &text->out_buf, &text->out_buf_len, &resplen,
+ "username", (unsigned char *) oparams->authid,
+ TRUE) != SASL_OK) {
+ result = SASL_FAIL;
+ goto FreeAllocatedMem;
+ }
if (add_to_challenge(params->utils,
&text->out_buf, &text->out_buf_len, &resplen,
@@ -3733,7 +3803,7 @@
if (strcmp(text->response_value, value) != 0) {
params->utils->seterror(params->utils->conn, 0,
"DIGEST-MD5: This server wants us to believe that he knows shared secret");
- result = SASL_FAIL;
+ result = SASL_BADSERV;
} else {
oparams->doneflag = 1;
oparams->param_version = 0;
|