00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 # include "config.h"
00025 #endif
00026
00027
00028 #include "scram.h"
00029
00030
00031 #include <stdlib.h>
00032
00033
00034 #include <limits.h>
00035
00036
00037 #include <string.h>
00038
00039
00040 #include "minmax.h"
00041
00042 #include "tokens.h"
00043 #include "parser.h"
00044 #include "printer.h"
00045 #include "gc.h"
00046 #include "memxor.h"
00047
00048 #define DEFAULT_SALT_BYTES 12
00049 #define SNONCE_ENTROPY_BYTES 18
00050
00051 struct scram_server_state
00052 {
00053 int step;
00054 char *gs2header;
00055 char *cfmb_str;
00056 char *sf_str;
00057 char *snonce;
00058 char *clientproof;
00059 char *storedkey;
00060 char *serverkey;
00061 char *authmessage;
00062 struct scram_client_first cf;
00063 struct scram_server_first sf;
00064 struct scram_client_final cl;
00065 struct scram_server_final sl;
00066 };
00067
00068 int
00069 _gsasl_scram_sha1_server_start (Gsasl_session * sctx, void **mech_data)
00070 {
00071 struct scram_server_state *state;
00072 char buf[MAX (SNONCE_ENTROPY_BYTES, DEFAULT_SALT_BYTES)];
00073 int rc;
00074
00075 state = (struct scram_server_state *) calloc (sizeof (*state), 1);
00076 if (state == NULL)
00077 return GSASL_MALLOC_ERROR;
00078
00079 rc = gsasl_nonce (buf, SNONCE_ENTROPY_BYTES);
00080 if (rc != GSASL_OK)
00081 goto end;
00082
00083 rc = gsasl_base64_to (buf, SNONCE_ENTROPY_BYTES,
00084 &state->snonce, NULL);
00085 if (rc != GSASL_OK)
00086 goto end;
00087
00088 rc = gsasl_nonce (buf, DEFAULT_SALT_BYTES);
00089 if (rc != GSASL_OK)
00090 goto end;
00091
00092 rc = gsasl_base64_to (buf, DEFAULT_SALT_BYTES,
00093 &state->sf.salt, NULL);
00094 if (rc != GSASL_OK)
00095 goto end;
00096
00097 *mech_data = state;
00098
00099 return GSASL_OK;
00100
00101 end:
00102 free (state->sf.salt);
00103 free (state->snonce);
00104 free (state);
00105 return rc;
00106 }
00107
00108 int
00109 _gsasl_scram_sha1_server_step (Gsasl_session * sctx,
00110 void *mech_data,
00111 const char *input,
00112 size_t input_len,
00113 char **output, size_t * output_len)
00114 {
00115 struct scram_server_state *state = mech_data;
00116 int res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
00117 int rc;
00118
00119 *output = NULL;
00120 *output_len = 0;
00121
00122 switch (state->step)
00123 {
00124 case 0:
00125 {
00126 if (input_len == 0)
00127 return GSASL_NEEDS_MORE;
00128
00129 if (scram_parse_client_first (input, input_len, &state->cf) < 0)
00130 return GSASL_MECHANISM_PARSE_ERROR;
00131
00132
00133 if (state->cf.cbflag != 'n' && state->cf.cbflag != 'y')
00134 return GSASL_AUTHENTICATION_ERROR;
00135
00136
00137 {
00138 char *tmp;
00139 rc = gsasl_saslprep (state->cf.username, GSASL_ALLOW_UNASSIGNED,
00140 &tmp, NULL);
00141 if (rc != GSASL_OK || *tmp == '\0')
00142 return GSASL_AUTHENTICATION_ERROR;
00143 gsasl_free (tmp);
00144 }
00145
00146 {
00147 const char *p;
00148
00149
00150 p = memchr (input, ',', input_len);
00151 if (!p)
00152 return GSASL_AUTHENTICATION_ERROR;
00153 p++;
00154 p = memchr (p, ',', input_len - (p - input));
00155 if (!p)
00156 return GSASL_AUTHENTICATION_ERROR;
00157 p++;
00158
00159 state->gs2header = malloc (p - input + 1);
00160 if (!state->gs2header)
00161 return GSASL_MALLOC_ERROR;
00162 memcpy (state->gs2header, input, p - input);
00163 state->gs2header[p - input] = '\0';
00164
00165 state->cfmb_str = malloc (input_len - (p - input) + 1);
00166 if (!state->cfmb_str)
00167 return GSASL_MALLOC_ERROR;
00168 memcpy (state->cfmb_str, p, input_len - (p - input));
00169 state->cfmb_str[input_len - (p - input)] = '\0';
00170 }
00171
00172
00173 {
00174 size_t cnlen = strlen (state->cf.client_nonce);
00175
00176 state->sf.nonce = malloc (cnlen + SNONCE_ENTROPY_BYTES + 1);
00177 if (!state->sf.nonce)
00178 return GSASL_MALLOC_ERROR;
00179
00180 memcpy (state->sf.nonce, state->cf.client_nonce, cnlen);
00181 memcpy (state->sf.nonce + cnlen, state->snonce,
00182 SNONCE_ENTROPY_BYTES);
00183 state->sf.nonce[cnlen + SNONCE_ENTROPY_BYTES] = '\0';
00184 }
00185
00186 gsasl_property_set (sctx, GSASL_AUTHID, state->cf.username);
00187 gsasl_property_set (sctx, GSASL_AUTHZID, state->cf.authzid);
00188
00189 {
00190 const char *p = gsasl_property_get (sctx, GSASL_SCRAM_ITER);
00191 if (p)
00192 state->sf.iter = strtoul (p, NULL, 10);
00193 if (!p || state->sf.iter == 0 || state->sf.iter == ULONG_MAX)
00194 state->sf.iter = 4096;
00195 }
00196
00197 {
00198 const char *p = gsasl_property_get (sctx, GSASL_SCRAM_SALT);
00199 if (p)
00200 {
00201 free (state->sf.salt);
00202 state->sf.salt = strdup (p);
00203 }
00204 }
00205
00206 rc = scram_print_server_first (&state->sf, &state->sf_str);
00207 if (rc != 0)
00208 return GSASL_MALLOC_ERROR;
00209
00210 *output = strdup (state->sf_str);
00211 if (!*output)
00212 return GSASL_MALLOC_ERROR;
00213 *output_len = strlen (*output);
00214
00215 state->step++;
00216 return GSASL_NEEDS_MORE;
00217 break;
00218 }
00219
00220 case 1:
00221 {
00222 if (scram_parse_client_final (input, input_len, &state->cl) < 0)
00223 return GSASL_MECHANISM_PARSE_ERROR;
00224
00225 if (strcmp (state->cl.nonce, state->sf.nonce) != 0)
00226 return GSASL_AUTHENTICATION_ERROR;
00227
00228
00229
00230 {
00231 size_t len;
00232 char *cbind;
00233
00234 rc = gsasl_base64_from (state->cl.cbind, strlen (state->cl.cbind),
00235 &cbind, &len);
00236 if (rc != 0)
00237 return rc;
00238
00239 if (len != strlen (state->gs2header))
00240 return GSASL_AUTHENTICATION_ERROR;
00241
00242 if (memcmp (cbind, state->gs2header, len) != 0)
00243 return GSASL_AUTHENTICATION_ERROR;
00244 }
00245
00246
00247
00248 {
00249 size_t len;
00250
00251 rc = gsasl_base64_from (state->cl.proof, strlen (state->cl.proof),
00252 &state->clientproof, &len);
00253 if (rc != 0)
00254 return rc;
00255 if (len != 20)
00256 return GSASL_MECHANISM_PARSE_ERROR;
00257 }
00258
00259 {
00260 const char *p;
00261
00262
00263 if ((p = gsasl_property_get (sctx, GSASL_PASSWORD)))
00264 {
00265 Gc_rc err;
00266 char *salt;
00267 size_t saltlen;
00268 char saltedpassword[20];
00269 char *clientkey;
00270 char *preppasswd;
00271
00272 rc = gsasl_saslprep (p, 0, &preppasswd, NULL);
00273 if (rc != GSASL_OK)
00274 return rc;
00275
00276 rc = gsasl_base64_from (state->sf.salt, strlen (state->sf.salt),
00277 &salt, &saltlen);
00278 if (rc != 0)
00279 {
00280 gsasl_free (preppasswd);
00281 return rc;
00282 }
00283
00284
00285 err = gc_pbkdf2_sha1 (preppasswd, strlen (preppasswd),
00286 salt, saltlen,
00287 state->sf.iter, saltedpassword, 20);
00288 gsasl_free (preppasswd);
00289 gsasl_free (salt);
00290 if (err != GC_OK)
00291 return GSASL_MALLOC_ERROR;
00292
00293
00294 #define CLIENT_KEY "Client Key"
00295 rc = gsasl_hmac_sha1 (saltedpassword, 20,
00296 CLIENT_KEY, strlen (CLIENT_KEY),
00297 &clientkey);
00298 if (rc != 0)
00299 return rc;
00300
00301
00302 rc = gsasl_sha1 (clientkey, 20, &state->storedkey);
00303 free (clientkey);
00304 if (rc != 0)
00305 return rc;
00306
00307
00308 #define SERVER_KEY "Server Key"
00309 rc = gsasl_hmac_sha1 (saltedpassword, 20,
00310 SERVER_KEY, strlen (SERVER_KEY),
00311 &state->serverkey);
00312 if (rc != 0)
00313 return rc;
00314 }
00315 else
00316 return GSASL_NO_PASSWORD;
00317
00318
00319 {
00320 size_t len;
00321 int n;
00322
00323
00324 p = memmem (input, input_len, ",p=", 3);
00325 if (!p)
00326 return GSASL_MECHANISM_PARSE_ERROR;
00327 len = p - input;
00328
00329 n = asprintf (&state->authmessage, "%s,%.*s,%.*s",
00330 state->cfmb_str,
00331 strlen (state->sf_str), state->sf_str,
00332 len, input);
00333 if (n <= 0 || !state->authmessage)
00334 return GSASL_MALLOC_ERROR;
00335 }
00336
00337
00338 {
00339 char *clientsignature;
00340 char *maybe_storedkey;
00341
00342
00343 rc = gsasl_hmac_sha1 (state->storedkey, 20,
00344 state->authmessage,
00345 strlen (state->authmessage),
00346 &clientsignature);
00347 if (rc != 0)
00348 return rc;
00349
00350
00351 memxor (clientsignature, state->clientproof, 20);
00352
00353 rc = gsasl_sha1 (clientsignature, 20, &maybe_storedkey);
00354 free (clientsignature);
00355 if (rc != 0)
00356 return rc;
00357
00358 rc = memcmp (state->storedkey, maybe_storedkey, 20);
00359 free (maybe_storedkey);
00360 if (rc != 0)
00361 return GSASL_AUTHENTICATION_ERROR;
00362 }
00363
00364
00365 {
00366 char *serversignature;
00367
00368
00369 rc = gsasl_hmac_sha1 (state->serverkey, 20,
00370 state->authmessage,
00371 strlen (state->authmessage),
00372 &serversignature);
00373 if (rc != 0)
00374 return rc;
00375
00376 rc = gsasl_base64_to (serversignature, 20,
00377 &state->sl.verifier, NULL);
00378 free (serversignature);
00379 if (rc != 0)
00380 return rc;
00381 }
00382 }
00383
00384 rc = scram_print_server_final (&state->sl, output);
00385 if (rc != 0)
00386 return GSASL_MALLOC_ERROR;
00387 *output_len = strlen (*output);
00388
00389 state->step++;
00390 return GSASL_OK;
00391 break;
00392 }
00393
00394 default:
00395 break;
00396 }
00397
00398 return res;
00399 }
00400
00401 void
00402 _gsasl_scram_sha1_server_finish (Gsasl_session * sctx, void *mech_data)
00403 {
00404 struct scram_server_state *state = mech_data;
00405
00406 if (!state)
00407 return;
00408
00409 free (state->cfmb_str);
00410 free (state->sf_str);
00411 free (state->snonce);
00412 free (state->clientproof);
00413 free (state->storedkey);
00414 free (state->serverkey);
00415 free (state->authmessage);
00416 scram_free_client_first (&state->cf);
00417 scram_free_server_first (&state->sf);
00418 scram_free_client_final (&state->cl);
00419 scram_free_server_final (&state->sl);
00420
00421 free (state);
00422 }