Report generated at: Mon May 28 19:22:30 CEST 2012
Total number of functions | 180 |
Number of low risk functions | 148 |
Number of moderate risk functions | 18 |
Number of high risk functions | 13 |
Number of untestable functions | 1 |
Cyclomatic Complexity | Risk Evaluation | |
0 - 10 | Simple module, without much risk | |
11 - 20 | More complex module, moderate risk | |
21 - 50 | Complex module, high risk | |
greater than 50 | Untestable module, very high risk |
Function Name | Modified Cyclo |
Number of
Statements |
Number of
Lines |
Source File | |
↓ | _gsasl_scram_sha1_server_step | 51 | 163 | 316 | ../../lib/scram/server.c |
int _gsasl_scram_sha1_server_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { struct scram_server_state *state = mech_data; int res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; int rc; *output = NULL; *output_len = 0; switch (state->step) { case 0: { if (input_len == 0) return GSASL_NEEDS_MORE; if (scram_parse_client_first (input, input_len, &state->cf) < 0) return GSASL_MECHANISM_PARSE_ERROR; /* In PLUS server mode, we require use of channel bindings. */ if (state->plus && state->cf.cbflag != 'p') return GSASL_AUTHENTICATION_ERROR; /* In non-PLUS mode, but where have channel bindings data (and thus advertised PLUS) we reject a client 'y' cbflag. */ if (!state->plus && state->cbtlsuniquelen > 0 && state->cf.cbflag == 'y') return GSASL_AUTHENTICATION_ERROR; /* Check that username doesn't fail SASLprep. */ { char *tmp; rc = gsasl_saslprep (state->cf.username, GSASL_ALLOW_UNASSIGNED, &tmp, NULL); if (rc != GSASL_OK || *tmp == '\0') return GSASL_AUTHENTICATION_ERROR; gsasl_free (tmp); } { const char *p; /* Save "gs2-header" and "message-bare" for next step. */ p = memchr (input, ',', input_len); if (!p) return GSASL_AUTHENTICATION_ERROR; p++; p = memchr (p, ',', input_len - (p - input)); if (!p) return GSASL_AUTHENTICATION_ERROR; p++; state->gs2header = malloc (p - input + 1); if (!state->gs2header) return GSASL_MALLOC_ERROR; memcpy (state->gs2header, input, p - input); state->gs2header[p - input] = '\0'; state->cfmb_str = malloc (input_len - (p - input) + 1); if (!state->cfmb_str) return GSASL_MALLOC_ERROR; memcpy (state->cfmb_str, p, input_len - (p - input)); state->cfmb_str[input_len - (p - input)] = '\0'; } /* Create new nonce. */ { size_t cnlen = strlen (state->cf.client_nonce); state->sf.nonce = malloc (cnlen + SNONCE_ENTROPY_BYTES + 1); if (!state->sf.nonce) return GSASL_MALLOC_ERROR; memcpy (state->sf.nonce, state->cf.client_nonce, cnlen); memcpy (state->sf.nonce + cnlen, state->snonce, SNONCE_ENTROPY_BYTES); state->sf.nonce[cnlen + SNONCE_ENTROPY_BYTES] = '\0'; } gsasl_property_set (sctx, GSASL_AUTHID, state->cf.username); gsasl_property_set (sctx, GSASL_AUTHZID, state->cf.authzid); { const char *p = gsasl_property_get (sctx, GSASL_SCRAM_ITER); if (p) state->sf.iter = strtoul (p, NULL, 10); if (!p || state->sf.iter == 0 || state->sf.iter == ULONG_MAX) state->sf.iter = 4096; } { const char *p = gsasl_property_get (sctx, GSASL_SCRAM_SALT); if (p) { free (state->sf.salt); state->sf.salt = strdup (p); } } rc = scram_print_server_first (&state->sf, &state->sf_str); if (rc != 0) return GSASL_MALLOC_ERROR; *output = strdup (state->sf_str); if (!*output) return GSASL_MALLOC_ERROR; *output_len = strlen (*output); state->step++; return GSASL_NEEDS_MORE; break; } case 1: { if (scram_parse_client_final (input, input_len, &state->cl) < 0) return GSASL_MECHANISM_PARSE_ERROR; if (strcmp (state->cl.nonce, state->sf.nonce) != 0) return GSASL_AUTHENTICATION_ERROR; /* Base64 decode the c= field and check that it matches client-first. Also check channel binding data. */ { size_t len; rc = gsasl_base64_from (state->cl.cbind, strlen (state->cl.cbind), &state->cbind, &len); if (rc != 0) return rc; if (state->cf.cbflag == 'p') { if (len < strlen (state->gs2header)) return GSASL_AUTHENTICATION_ERROR; if (memcmp (state->cbind, state->gs2header, strlen (state->gs2header)) != 0) return GSASL_AUTHENTICATION_ERROR; if (len - strlen (state->gs2header) != state->cbtlsuniquelen) return GSASL_AUTHENTICATION_ERROR; if (memcmp (state->cbind + strlen (state->gs2header), state->cbtlsunique, state->cbtlsuniquelen) != 0) return GSASL_AUTHENTICATION_ERROR; } else { if (len != strlen (state->gs2header)) return GSASL_AUTHENTICATION_ERROR; if (memcmp (state->cbind, state->gs2header, len) != 0) return GSASL_AUTHENTICATION_ERROR; } } /* Base64 decode client proof and check that length matches SHA-1 size. */ { size_t len; rc = gsasl_base64_from (state->cl.proof, strlen (state->cl.proof), &state->clientproof, &len); if (rc != 0) return rc; if (len != 20) return GSASL_MECHANISM_PARSE_ERROR; } { const char *p; /* Get StoredKey and ServerKey */ if ((p = gsasl_property_get (sctx, GSASL_PASSWORD))) { Gc_rc err; char *salt; size_t saltlen; char saltedpassword[20]; char *clientkey; char *preppasswd; rc = gsasl_saslprep (p, 0, &preppasswd, NULL); if (rc != GSASL_OK) return rc; rc = gsasl_base64_from (state->sf.salt, strlen (state->sf.salt), &salt, &saltlen); if (rc != 0) { gsasl_free (preppasswd); return rc; } /* SaltedPassword := Hi(password, salt) */ err = gc_pbkdf2_sha1 (preppasswd, strlen (preppasswd), salt, saltlen, state->sf.iter, saltedpassword, 20); gsasl_free (preppasswd); gsasl_free (salt); if (err != GC_OK) return GSASL_MALLOC_ERROR; /* ClientKey := HMAC(SaltedPassword, "Client Key") */ #define CLIENT_KEY "Client Key" rc = gsasl_hmac_sha1 (saltedpassword, 20, CLIENT_KEY, strlen (CLIENT_KEY), &clientkey); if (rc != 0) return rc; /* StoredKey := H(ClientKey) */ rc = gsasl_sha1 (clientkey, 20, &state->storedkey); free (clientkey); if (rc != 0) return rc; /* ServerKey := HMAC(SaltedPassword, "Server Key") */ #define SERVER_KEY "Server Key" rc = gsasl_hmac_sha1 (saltedpassword, 20, SERVER_KEY, strlen (SERVER_KEY), &state->serverkey); if (rc != 0) return rc; } else return GSASL_NO_PASSWORD; /* Compute AuthMessage */ { size_t len; int n; /* Get client-final-message-without-proof. */ p = memmem (input, input_len, ",p=", 3); if (!p) return GSASL_MECHANISM_PARSE_ERROR; len = p - input; n = asprintf (&state->authmessage, "%s,%.*s,%.*s", state->cfmb_str, (int) strlen (state->sf_str), state->sf_str, (int) len, input); if (n <= 0 || !state->authmessage) return GSASL_MALLOC_ERROR; } /* Check client proof. */ { char *clientsignature; char *maybe_storedkey; /* ClientSignature := HMAC(StoredKey, AuthMessage) */ rc = gsasl_hmac_sha1 (state->storedkey, 20, state->authmessage, strlen (state->authmessage), &clientsignature); if (rc != 0) return rc; /* ClientKey := ClientProof XOR ClientSignature */ memxor (clientsignature, state->clientproof, 20); rc = gsasl_sha1 (clientsignature, 20, &maybe_storedkey); free (clientsignature); if (rc != 0) return rc; rc = memcmp (state->storedkey, maybe_storedkey, 20); free (maybe_storedkey); if (rc != 0) return GSASL_AUTHENTICATION_ERROR; } /* Generate server verifier. */ { char *serversignature; /* ServerSignature := HMAC(ServerKey, AuthMessage) */ rc = gsasl_hmac_sha1 (state->serverkey, 20, state->authmessage, strlen (state->authmessage), &serversignature); if (rc != 0) return rc; rc = gsasl_base64_to (serversignature, 20, &state->sl.verifier, NULL); free (serversignature); if (rc != 0) return rc; } } rc = scram_print_server_final (&state->sl, output); if (rc != 0) return GSASL_MALLOC_ERROR; *output_len = strlen (*output); state->step++; return GSASL_OK; break; } default: break; } return res; } |
|||||
↓ | _gsasl_scram_sha1_client_step | 41 | 154 | 283 | ../../lib/scram/client.c |
int _gsasl_scram_sha1_client_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { struct scram_client_state *state = mech_data; int res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; int rc; *output = NULL; *output_len = 0; switch (state->step) { case 0: { const char *p; if (state->plus) { state->cf.cbflag = 'p'; state->cf.cbname = strdup ("tls-unique"); } else { if (state->cbtlsuniquelen > 0) state->cf.cbflag = 'y'; else state->cf.cbflag = 'n'; } p = gsasl_property_get (sctx, GSASL_AUTHID); if (!p) return GSASL_NO_AUTHID; rc = gsasl_saslprep (p, GSASL_ALLOW_UNASSIGNED, &state->cf.username, NULL); if (rc != GSASL_OK) return rc; p = gsasl_property_get (sctx, GSASL_AUTHZID); if (p) state->cf.authzid = strdup (p); rc = scram_print_client_first (&state->cf, output); if (rc == -2) return GSASL_MALLOC_ERROR; else if (rc != 0) return GSASL_AUTHENTICATION_ERROR; *output_len = strlen (*output); /* Point p to client-first-message-bare. */ p = strchr (*output, ','); if (!p) return GSASL_AUTHENTICATION_ERROR; p++; p = strchr (p, ','); if (!p) return GSASL_AUTHENTICATION_ERROR; p++; /* Save "client-first-message-bare" for the next step. */ state->cfmb = strdup (p); if (!state->cfmb) return GSASL_MALLOC_ERROR; /* Prepare B64("cbind-input") for the next step. */ if (state->cf.cbflag == 'p') { size_t len = (p - *output) + state->cbtlsuniquelen; char *cbind_input = malloc (len); if (cbind_input == NULL) return GSASL_MALLOC_ERROR; memcpy (cbind_input, *output, p - *output); memcpy (cbind_input + (p - *output), state->cbtlsunique, state->cbtlsuniquelen); rc = gsasl_base64_to (cbind_input, len, &state->cl.cbind, NULL); free (cbind_input); } else rc = gsasl_base64_to (*output, p - *output, &state->cl.cbind, NULL); if (rc != 0) return rc; /* We are done. */ state->step++; return GSASL_NEEDS_MORE; break; } case 1: { if (scram_parse_server_first (input, input_len, &state->sf) < 0) return GSASL_MECHANISM_PARSE_ERROR; if (strlen (state->sf.nonce) < strlen (state->cf.client_nonce) || memcmp (state->cf.client_nonce, state->sf.nonce, strlen (state->cf.client_nonce)) != 0) return GSASL_AUTHENTICATION_ERROR; state->cl.nonce = strdup (state->sf.nonce); if (!state->cl.nonce) return GSASL_MALLOC_ERROR; /* Save salt/iter as properties, so that client callback can access them. */ { char *str = NULL; int n; n = asprintf (&str, "%lu", (unsigned long) state->sf.iter); if (n < 0 || str == NULL) return GSASL_MALLOC_ERROR; gsasl_property_set (sctx, GSASL_SCRAM_ITER, str); free (str); } gsasl_property_set (sctx, GSASL_SCRAM_SALT, state->sf.salt); /* Generate ClientProof. */ { char saltedpassword[20]; char *clientkey; char *storedkey; char *clientsignature; char clientproof[20]; const char *p; /* Get SaltedPassword. */ p = gsasl_property_get (sctx, GSASL_SCRAM_SALTED_PASSWORD); if (p && strlen (p) == 40 && hex_p (p)) sha1_hex_to_byte (saltedpassword, p); else if ((p = gsasl_property_get (sctx, GSASL_PASSWORD)) != NULL) { Gc_rc err; char *salt; size_t saltlen; char *preppasswd; rc = gsasl_saslprep (p, 0, &preppasswd, NULL); if (rc != GSASL_OK) return rc; rc = gsasl_base64_from (state->sf.salt, strlen (state->sf.salt), &salt, &saltlen); if (rc != 0) { gsasl_free (preppasswd); return rc; } /* SaltedPassword := Hi(password, salt) */ err = gc_pbkdf2_sha1 (preppasswd, strlen (preppasswd), salt, saltlen, state->sf.iter, saltedpassword, 20); gsasl_free (preppasswd); gsasl_free (salt); if (err != GC_OK) return GSASL_MALLOC_ERROR; } else return GSASL_NO_PASSWORD; /* Get client-final-message-without-proof. */ { char *cfmwp; int n; state->cl.proof = strdup ("p"); rc = scram_print_client_final (&state->cl, &cfmwp); if (rc != 0) return GSASL_MALLOC_ERROR; free (state->cl.proof); /* Compute AuthMessage */ n = asprintf (&state->authmessage, "%s,%.*s,%.*s", state->cfmb, (int) input_len, input, (int) (strlen (cfmwp) - 4), cfmwp); free (cfmwp); if (n <= 0 || !state->authmessage) return GSASL_MALLOC_ERROR; } /* ClientKey := HMAC(SaltedPassword, "Client Key") */ #define CLIENT_KEY "Client Key" rc = gsasl_hmac_sha1 (saltedpassword, 20, CLIENT_KEY, strlen (CLIENT_KEY), &clientkey); if (rc != 0) return rc; /* StoredKey := H(ClientKey) */ rc = gsasl_sha1 (clientkey, 20, &storedkey); if (rc != 0) { free (clientkey); return rc; } /* ClientSignature := HMAC(StoredKey, AuthMessage) */ rc = gsasl_hmac_sha1 (storedkey, 20, state->authmessage, strlen (state->authmessage), &clientsignature); free (storedkey); if (rc != 0) { free (clientkey); return rc; } /* ClientProof := ClientKey XOR ClientSignature */ memcpy (clientproof, clientkey, 20); memxor (clientproof, clientsignature, 20); free (clientkey); free (clientsignature); rc = gsasl_base64_to (clientproof, 20, &state->cl.proof, NULL); if (rc != 0) return rc; /* Generate ServerSignature, for comparison in next step. */ { char *serverkey; char *serversignature; /* ServerKey := HMAC(SaltedPassword, "Server Key") */ #define SERVER_KEY "Server Key" rc = gsasl_hmac_sha1 (saltedpassword, 20, SERVER_KEY, strlen (SERVER_KEY), &serverkey); if (rc != 0) return rc; /* ServerSignature := HMAC(ServerKey, AuthMessage) */ rc = gsasl_hmac_sha1 (serverkey, 20, state->authmessage, strlen (state->authmessage), &serversignature); gsasl_free (serverkey); if (rc != 0) return rc; rc = gsasl_base64_to (serversignature, 20, &state->serversignature, NULL); gsasl_free (serversignature); if (rc != 0) return rc; } } rc = scram_print_client_final (&state->cl, output); if (rc != 0) return GSASL_MALLOC_ERROR; *output_len = strlen (*output); state->step++; return GSASL_NEEDS_MORE; break; } case 2: { if (scram_parse_server_final (input, input_len, &state->sl) < 0) return GSASL_MECHANISM_PARSE_ERROR; if (strcmp (state->sl.verifier, state->serversignature) != 0) return GSASL_AUTHENTICATION_ERROR; state->step++; return GSASL_OK; break; } default: break; } return res; } |
|||||
↓ | scram_parse_client_first | 40 | 95 | 141 | ../../lib/scram/parser.c |
int scram_parse_client_first (const char *str, size_t len, struct scram_client_first *cf) { /* Minimum client first string is 'n,,n=a,r=b'. */ if (strnlen (str, len) < 10) return -1; if (len == 0 || (*str != 'n' && *str != 'y' && *str != 'p')) return -1; cf->cbflag = *str; str++, len--; if (cf->cbflag == 'p') { const char *p; if (len == 0 || *str != '=') return -1; str++, len--; p = memchr (str, ',', len); if (!p) return -1; cf->cbname = malloc (p - str + 1); if (!cf->cbname) return -1; memcpy (cf->cbname, str, p - str); cf->cbname[p - str] = '\0'; len -= (p - str); str += (p - str); } if (len == 0 || *str != ',') return -1; str++, len--; if (len == 0) return -1; if (*str == 'a') { const char *p; size_t l; str++, len--; if (len == 0 || *str != '=') return -1; str++, len--; p = memchr (str, ',', len); if (!p) return -1; l = p - str; if (len < l) return -1; cf->authzid = unescape (str, l); if (!cf->authzid) return -1; str = p; len -= l; } if (len == 0 || *str != ',') return -1; str++, len--; if (len == 0 || *str != 'n') return -1; str++, len--; if (len == 0 || *str != '=') return -1; str++, len--; { const char *p; size_t l; p = memchr (str, ',', len); if (!p) return -1; l = p - str; if (len < l) return -1; cf->username = unescape (str, l); if (!cf->username) return -1; str = p; len -= l; } if (len == 0 || *str != ',') return -1; str++, len--; if (len == 0 || *str != 'r') return -1; str++, len--; if (len == 0 || *str != '=') return -1; str++, len--; { const char *p; size_t l; p = memchr (str, ',', len); if (!p) p = str + len; if (!p) return -1; l = p - str; if (len < l) return -1; cf->client_nonce = malloc (l + 1); if (!cf->client_nonce) return -1; memcpy (cf->client_nonce, str, l); cf->client_nonce[l] = '\0'; str = p; len -= l; } /* FIXME check that any extension fields follow valid syntax. */ if (scram_valid_client_first (cf) < 0) return -1; return 0; } |
|||||
↓ | digest_md5_print_response | 38 | 86 | 146 | ../../lib/digest-md5/printer.c |
char * digest_md5_print_response (digest_md5_response * r) { char *out = NULL; const char *qop = NULL; const char *cipher = NULL; /* Below we assume the mandatory fields are present, verify that first to avoid crashes. */ if (digest_md5_validate_response (r) != 0) return NULL; if (r->qop & DIGEST_MD5_QOP_AUTH_CONF) qop = "qop=auth-conf"; else if (r->qop & DIGEST_MD5_QOP_AUTH_INT) qop = "qop=auth-int"; else if (r->qop & DIGEST_MD5_QOP_AUTH) qop = "qop=auth"; if (r->cipher & DIGEST_MD5_CIPHER_3DES) cipher = "cipher=3des"; else if (r->cipher & DIGEST_MD5_CIPHER_DES) cipher = "cipher=des"; else if (r->cipher & DIGEST_MD5_CIPHER_RC4_40) cipher = "cipher=rc4-40"; else if (r->cipher & DIGEST_MD5_CIPHER_RC4) cipher = "cipher=rc4"; else if (r->cipher & DIGEST_MD5_CIPHER_RC4_56) cipher = "cipher=rc4-56"; else if (r->cipher & DIGEST_MD5_CIPHER_AES_CBC) cipher = "cipher=aes-cbc"; else if (r->cipher & DIGEST_MD5_CIPHER_3DES) cipher = "cipher=3des"; if (r->username) if (comma_append (&out, "username", r->username, 1) < 0) { free (out); return NULL; } if (r->realm) if (comma_append (&out, "realm", r->realm, 1) < 0) { free (out); return NULL; } if (r->nonce) if (comma_append (&out, "nonce", r->nonce, 1) < 0) { free (out); return NULL; } if (r->cnonce) if (comma_append (&out, "cnonce", r->cnonce, 1) < 0) { free (out); return NULL; } if (r->nc) { char *tmp; if (asprintf (&tmp, "%08lx", r->nc) < 0) { free (out); return NULL; } if (comma_append (&out, "nc", tmp, 0) < 0) { free (tmp); free (out); return NULL; } free (tmp); } if (qop) if (comma_append (&out, qop, NULL, 0) < 0) { free (out); return NULL; } if (r->digesturi) if (comma_append (&out, "digest-uri", r->digesturi, 1) < 0) { free (out); return NULL; } if (r->response) if (comma_append (&out, "response", r->response, 0) < 0) { free (out); return NULL; } if (r->clientmaxbuf) { char *tmp; if (asprintf (&tmp, "%lu", r->clientmaxbuf) < 0) { free (out); return NULL; } if (comma_append (&out, "maxbuf", tmp, 0) < 0) { free (tmp); free (out); return NULL; } free (tmp); } if (r->utf8) if (comma_append (&out, "charset", "utf-8", 0) < 0) { free (out); return NULL; } if (cipher) if (comma_append (&out, cipher, NULL, 0) < 0) { free (out); return NULL; } if (r->authzid) if (comma_append (&out, "authzid", r->authzid, 1) < 0) { free (out); return NULL; } return out; } |
|||||
↓ | parse_response | 37 | 95 | 171 | ../../lib/digest-md5/parser.c |
static int parse_response (char *response, digest_md5_response * out) { char *value; memset (out, 0, sizeof (*out)); /* The size of a digest-response MUST be less than 4096 bytes. */ if (strlen (response) >= 4096) return -1; while (*response != '\0') switch (digest_md5_getsubopt (&response, digest_response_opts, &value)) { case RESPONSE_USERNAME: /* This directive is required and MUST be present exactly once; otherwise, authentication fails. */ if (out->username) return -1; out->username = strdup (value); if (!out->username) return -1; break; case RESPONSE_REALM: /* This directive is required if the server provided any realms in the "digest-challenge", in which case it may appear exactly once and its value SHOULD be one of those realms. */ if (out->realm) return -1; out->realm = strdup (value); if (!out->realm) return -1; break; case RESPONSE_NONCE: /* This directive is required and MUST be present exactly once; otherwise, authentication fails. */ if (out->nonce) return -1; out->nonce = strdup (value); if (!out->nonce) return -1; break; case RESPONSE_CNONCE: /* This directive is required and MUST be present exactly once; otherwise, authentication fails. */ if (out->cnonce) return -1; out->cnonce = strdup (value); if (!out->cnonce) return -1; break; case RESPONSE_NC: /* This directive is required and MUST be present exactly once; otherwise, authentication fails. */ if (out->nc) return -1; /* nc-value = 8LHEX */ if (strlen (value) != 8) return -1; out->nc = strtoul (value, NULL, 16); /* FIXME: error handling. */ break; case RESPONSE_QOP: /* If present, it may appear exactly once and its value MUST be one of the alternatives in qop-options. */ if (out->qop) return -1; if (strcmp (value, "auth") == 0) out->qop = DIGEST_MD5_QOP_AUTH; else if (strcmp (value, "auth-int") == 0) out->qop = DIGEST_MD5_QOP_AUTH_INT; else if (strcmp (value, "auth-conf") == 0) out->qop = DIGEST_MD5_QOP_AUTH_CONF; else return -1; break; case RESPONSE_DIGEST_URI: /* This directive is required and MUST be present exactly once; if multiple instances are present, the client MUST abort the authentication exchange. */ if (out->digesturi) return -1; /* FIXME: sub-parse. */ out->digesturi = strdup (value); if (!out->digesturi) return -1; break; case RESPONSE_RESPONSE: /* This directive is required and MUST be present exactly once; otherwise, authentication fails. */ if (*out->response) return -1; /* A string of 32 hex digits */ if (strlen (value) != DIGEST_MD5_RESPONSE_LENGTH) return -1; strcpy (out->response, value); break; case RESPONSE_MAXBUF: /* This directive may appear at most once; if multiple instances are present, the server MUST abort the authentication exchange. */ if (out->clientmaxbuf) return -1; out->clientmaxbuf = strtoul (value, NULL, 10); /* FIXME: error handling. */ /* If the value is less or equal to 16 (<<32 for aes-cbc>>) or bigger than 16777215 (i.e. 2**24-1), the server MUST abort the authentication exchange. */ if (out->clientmaxbuf <= 16 || out->clientmaxbuf > 16777215) return -1; break; case RESPONSE_CHARSET: if (strcmp (DEFAULT_CHARSET, value) != 0) return -1; out->utf8 = 1; break; case RESPONSE_CIPHER: if (out->cipher) return -1; if (strcmp (value, "3des") == 0) out->cipher = DIGEST_MD5_CIPHER_3DES; else if (strcmp (value, "des") == 0) out->cipher = DIGEST_MD5_CIPHER_DES; else if (strcmp (value, "rc4-40") == 0) out->cipher = DIGEST_MD5_CIPHER_RC4_40; else if (strcmp (value, "rc4") == 0) out->cipher = DIGEST_MD5_CIPHER_RC4; else if (strcmp (value, "rc4-56") == 0) out->cipher = DIGEST_MD5_CIPHER_RC4_56; else if (strcmp (value, "aes-cbc") == 0) out->cipher = DIGEST_MD5_CIPHER_AES_CBC; else return -1; break; case RESPONSE_AUTHZID: /* This directive may appear at most once; if multiple instances are present, the server MUST abort the authentication exchange. < |
|||||
↓ | digest_md5_hmac | 37 | 162 | 236 | ../../lib/digest-md5/digesthmac.c |
int digest_md5_hmac (char *output, char secret[MD5LEN], const char *nonce, unsigned long nc, const char *cnonce, digest_md5_qop qop, const char *authzid, const char *digesturi, int rspauth, digest_md5_cipher cipher, char *kic, char *kis, char *kcc, char *kcs) { const char *a2string = rspauth ? COLON : A2_PRE; char nchex[9]; char a1hexhash[2 * MD5LEN]; char a2hexhash[2 * MD5LEN]; char hash[MD5LEN]; char *tmp, *p; size_t tmplen; int rc; int i; /* A1 */ tmplen = MD5LEN + strlen (COLON) + strlen (nonce) + strlen (COLON) + strlen (cnonce); if (authzid && strlen (authzid) > 0) tmplen += strlen (COLON) + strlen (authzid); p = tmp = malloc (tmplen); if (tmp == NULL) return -1; memcpy (p, secret, MD5LEN); p += MD5LEN; memcpy (p, COLON, strlen (COLON)); p += strlen (COLON); memcpy (p, nonce, strlen (nonce)); p += strlen (nonce); memcpy (p, COLON, strlen (COLON)); p += strlen (COLON); memcpy (p, cnonce, strlen (cnonce)); p += strlen (cnonce); if (authzid && strlen (authzid) > 0) { memcpy (p, COLON, strlen (COLON)); p += strlen (COLON); memcpy (p, authzid, strlen (authzid)); p += strlen (authzid); } rc = gc_md5 (tmp, tmplen, hash); free (tmp); if (rc) return rc; if (kic) { char hash2[MD5LEN]; char q[MD5LEN + DERIVE_CLIENT_INTEGRITY_KEY_STRING_LEN]; size_t qlen = MD5LEN + DERIVE_CLIENT_INTEGRITY_KEY_STRING_LEN; memcpy (q, hash, MD5LEN); memcpy (q + MD5LEN, DERIVE_CLIENT_INTEGRITY_KEY_STRING, DERIVE_CLIENT_INTEGRITY_KEY_STRING_LEN); rc = gc_md5 (q, qlen, hash2); if (rc) return rc; memcpy (kic, hash2, MD5LEN); } if (kis) { char hash2[MD5LEN]; char q[MD5LEN + DERIVE_SERVER_INTEGRITY_KEY_STRING_LEN]; size_t qlen = MD5LEN + DERIVE_SERVER_INTEGRITY_KEY_STRING_LEN; memcpy (q, hash, MD5LEN); memcpy (q + MD5LEN, DERIVE_SERVER_INTEGRITY_KEY_STRING, DERIVE_SERVER_INTEGRITY_KEY_STRING_LEN); rc = gc_md5 (q, qlen, hash2); if (rc) return rc; memcpy (kis, hash2, MD5LEN); } if (kcc) { char hash2[MD5LEN]; int n; char q[MD5LEN + DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING_LEN]; if (cipher == DIGEST_MD5_CIPHER_RC4_40) n = 5; else if (cipher == DIGEST_MD5_CIPHER_RC4_56) n = 7; else n = MD5LEN; memcpy (q, hash, n); memcpy (q + n, DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING, DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING_LEN); rc = gc_md5 (q, n + DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING_LEN, hash2); if (rc) return rc; memcpy (kcc, hash2, MD5LEN); } if (kcs) { char hash2[MD5LEN]; int n; char q[MD5LEN + DERIVE_SERVER_CONFIDENTIALITY_KEY_STRING_LEN]; if (cipher == DIGEST_MD5_CIPHER_RC4_40) n = 5; else if (cipher == DIGEST_MD5_CIPHER_RC4_56) n = 7; else n = MD5LEN; memcpy (q, hash, n); memcpy (q + n, DERIVE_SERVER_CONFIDENTIALITY_KEY_STRING, DERIVE_SERVER_CONFIDENTIALITY_KEY_STRING_LEN); rc = gc_md5 (q, n + DERIVE_SERVER_CONFIDENTIALITY_KEY_STRING_LEN, hash2); if (rc) return rc; memcpy (kcs, hash2, MD5LEN); } for (i = 0; i < MD5LEN; i++) { a1hexhash[2 * i + 1] = HEXCHAR (hash[i]); a1hexhash[2 * i + 0] = HEXCHAR (hash[i] >> 4); } /* A2 */ tmplen = strlen (a2string) + strlen (digesturi); if (qop & DIGEST_MD5_QOP_AUTH_INT || qop & DIGEST_MD5_QOP_AUTH_CONF) tmplen += strlen (A2_POST); p = tmp = malloc (tmplen); if (tmp == NULL) return -1; memcpy (p, a2string, strlen (a2string)); p += strlen (a2string); memcpy (p, digesturi, strlen (digesturi)); p += strlen (digesturi); if (qop & DIGEST_MD5_QOP_AUTH_INT || qop & DIGEST_MD5_QOP_AUTH_CONF) memcpy (p, A2_POST, strlen (A2_POST)); rc = gc_md5 (tmp, tmplen, hash); free (tmp); if (rc) return rc; for (i = 0; i < MD5LEN; i++) { a2hexhash[2 * i + 1] = HEXCHAR (hash[i]); a2hexhash[2 * i + 0] = HEXCHAR (hash[i] >> 4); } /* response_value */ sprintf (nchex, "%08lx", nc); tmplen = 2 * MD5LEN + strlen (COLON) + strlen (nonce) + strlen (COLON) + strlen (nchex) + strlen (COLON) + strlen (cnonce) + strlen (COLON); if (qop & DIGEST_MD5_QOP_AUTH_CONF) tmplen += strlen (QOP_AUTH_CONF); else if (qop & DIGEST_MD5_QOP_AUTH_INT) tmplen += strlen (QOP_AUTH_INT); else if (qop & DIGEST_MD5_QOP_AUTH) tmplen += strlen (QOP_AUTH); tmplen += strlen (COLON) + 2 * MD5LEN; p = tmp = malloc (tmplen); if (tmp == NULL) return -1; memcpy (p, a1hexhash, 2 * MD5LEN); p += 2 * MD5LEN; memcpy (p, COLON, strlen (COLON)); p += strlen (COLON); memcpy (p, nonce, strlen (nonce)); p += strlen (nonce); memcpy (p, COLON, strlen (COLON)); p += strlen (COLON); memcpy (p, nchex, strlen (nchex)); p += strlen (nchex); memcpy (p, COLON, strlen (COLON)); p += strlen (COLON); memcpy (p, cnonce, strlen (cnonce)); p += strlen (cnonce); memcpy (p, COLON, strlen (COLON)); p += strlen (COLON); if (qop & DIGEST_MD5_QOP_AUTH_CONF) { memcpy (p, QOP_AUTH_CONF, strlen (QOP_AUTH_CONF)); p += strlen (QOP_AUTH_CONF); } else if (qop & DIGEST_MD5_QOP_AUTH_INT) { memcpy (p, QOP_AUTH_INT, strlen (QOP_AUTH_INT)); p += strlen (QOP_AUTH_INT); } else if (qop & DIGEST_MD5_QOP_AUTH) { memcpy (p, QOP_AUTH, strlen (QOP_AUTH)); p += strlen (QOP_AUTH); } memcpy (p, COLON, strlen (COLON)); p += strlen (COLON); memcpy (p, a2hexhash, 2 * MD5LEN); rc = gc_md5 (tmp, tmplen, hash); free (tmp); if (rc) return rc; for (i = 0; i < MD5LEN; i++) { output[2 * i + 1] = HEXCHAR (hash[i]); output[2 * i + 0] = HEXCHAR (hash[i] >> 4); } output[32] = '\0'; return 0; } |
|||||
↓ | digest_md5_print_challenge | 36 | 94 | 168 | ../../lib/digest-md5/printer.c |
char * digest_md5_print_challenge (digest_md5_challenge * c) { char *out = NULL; size_t i; /* Below we assume the mandatory fields are present, verify that first to avoid crashes. */ if (digest_md5_validate_challenge (c) != 0) return NULL; for (i = 0; i < c->nrealms; i++) { if (comma_append (&out, "realm", c->realms[i], 1) < 0) { free (out); return NULL; } } if (c->nonce) if (comma_append (&out, "nonce", c->nonce, 1) < 0) { free (out); return NULL; } if (c->qops) { char *tmp = NULL; if (c->qops & DIGEST_MD5_QOP_AUTH) if (comma_append (&tmp, "auth", NULL, 0) < 0) { free (tmp); free (out); return NULL; } if (c->qops & DIGEST_MD5_QOP_AUTH_INT) if (comma_append (&tmp, "auth-int", NULL, 0) < 0) { free (tmp); free (out); return NULL; } if (c->qops & DIGEST_MD5_QOP_AUTH_CONF) if (comma_append (&tmp, "auth-conf", NULL, 0) < 0) { free (tmp); free (out); return NULL; } if (comma_append (&out, "qop", tmp, 1) < 0) { free (tmp); free (out); return NULL; } free (tmp); } if (c->stale) if (comma_append (&out, "stale", "true", 0) < 0) { free (out); return NULL; } if (c->servermaxbuf) { char *tmp; if (asprintf (&tmp, "%lu", c->servermaxbuf) < 0) { free (out); return NULL; } if (comma_append (&out, "maxbuf", tmp, 0) < 0) { free (out); return NULL; } free (tmp); } if (c->utf8) if (comma_append (&out, "charset", "utf-8", 0) < 0) { free (out); return NULL; } if (comma_append (&out, "algorithm", "md5-sess", 0) < 0) { free (out); return NULL; } if (c->ciphers) { char *tmp = NULL; if (c->ciphers & DIGEST_MD5_CIPHER_3DES) if (comma_append (&tmp, "3des", NULL, 0) < 0) { free (tmp); free (out); return NULL; } if (c->ciphers & DIGEST_MD5_CIPHER_DES) if (comma_append (&tmp, "des", NULL, 0) < 0) { free (tmp); free (out); return NULL; } if (c->ciphers & DIGEST_MD5_CIPHER_RC4_40) if (comma_append (&tmp, "rc4-40", NULL, 0) < 0) { free (tmp); free (out); return NULL; } if (c->ciphers & DIGEST_MD5_CIPHER_RC4) if (comma_append (&tmp, "rc4", NULL, 0) < 0) { free (tmp); free (out); return NULL; } if (c->ciphers & DIGEST_MD5_CIPHER_RC4_56) if (comma_append (&tmp, "rc4-56", NULL, 0) < 0) { free (tmp); free (out); return NULL; } if (c->ciphers & DIGEST_MD5_CIPHER_AES_CBC) if (comma_append (&tmp, "aes-cbc", NULL, 0) < 0) { free (tmp); free (out); return NULL; } if (comma_append (&out, "cipher", tmp, 1) < 0) { free (tmp); free (out); return NULL; } free (tmp); } return out; } |
|||||
↓ | scram_parse_client_final | 34 | 82 | 127 | ../../lib/scram/parser.c |
int scram_parse_client_final (const char *str, size_t len, struct scram_client_final *cl) { /* Minimum client final string is 'c=biws,r=ab,p=ab=='. */ if (strnlen (str, len) < 18) return -1; if (len == 0 || *str != 'c') return -1; str++, len--; if (len == 0 || *str != '=') return -1; str++, len--; { const char *p; size_t l; p = memchr (str, ',', len); if (!p) return -1; l = p - str; if (len < l) return -1; cl->cbind = malloc (l + 1); if (!cl->cbind) return -1; memcpy (cl->cbind, str, l); cl->cbind[l] = '\0'; str = p; len -= l; } if (len == 0 || *str != ',') return -1; str++, len--; if (len == 0 || *str != 'r') return -1; str++, len--; if (len == 0 || *str != '=') return -1; str++, len--; { const char *p; size_t l; p = memchr (str, ',', len); if (!p) return -1; l = p - str; if (len < l) return -1; cl->nonce = malloc (l + 1); if (!cl->nonce) return -1; memcpy (cl->nonce, str, l); cl->nonce[l] = '\0'; str = p; len -= l; } if (len == 0 || *str != ',') return -1; str++, len--; /* Ignore extensions. */ while (len > 0 && c_isalpha (*str) && *str != 'p') { const char *p; size_t l; str++, len--; if (len == 0 || *str != '=') return -1; str++, len--; p = memchr (str, ',', len); if (!p) return -1; p++; l = p - str; if (len < l) return -1; str = p; len -= l; } if (len == 0 || *str != 'p') return -1; str++, len--; if (len == 0 || *str != '=') return -1; str++, len--; /* Sanity check proof. */ if (memchr (str, '\0', len)) return -1; cl->proof = malloc (len + 1); if (!cl->proof) return -1; memcpy (cl->proof, str, len); cl->proof[len] = '\0'; if (scram_valid_client_final (cl) < 0) return -1; return 0; } |
|||||
↓ | digest_md5_getsubopt | 33 | 38 | 71 | ../../lib/digest-md5/getsubopt.c |
int digest_md5_getsubopt (char **optionp, const char *const *tokens, char **valuep) { char *endp, *vstart; int cnt; int inside_quote = 0; if (**optionp == '\0') return -1; /* Find end of next token. */ endp = *optionp; while (*endp != '\0' && (inside_quote || (!inside_quote && *endp != ','))) { if (*endp == '"') inside_quote = !inside_quote; endp++; } /* Find start of value. */ vstart = memchr (*optionp, '=', endp - *optionp); if (vstart == NULL) vstart = endp; /* Try to match the characters between *OPTIONP and VSTART against one of the TOKENS. */ for (cnt = 0; tokens[cnt] != NULL; ++cnt) if (memcmp (*optionp, tokens[cnt], vstart - *optionp) == 0 && tokens[cnt][vstart - *optionp] == '\0') { /* We found the current option in TOKENS. */ *valuep = vstart != endp ? vstart + 1 : NULL; while (*valuep && (**valuep == ' ' || **valuep == '\t' || **valuep == '\r' || **valuep == '\n' || **valuep == '"')) (*valuep)++; if (*endp != '\0') { *endp = '\0'; *optionp = endp + 1; } else *optionp = endp; endp--; while (*endp == ' ' || *endp == '\t' || *endp == '\r' || *endp == '\n' || *endp == '"') *endp-- = '\0'; while (**optionp == ' ' || **optionp == '\t' || **optionp == '\r' || **optionp == '\n') (*optionp)++; return cnt; } /* The current suboption does not match any option. */ *valuep = *optionp; if (*endp != '\0') *endp++ = '\0'; *optionp = endp; while (**optionp == ' ' || **optionp == '\t' || **optionp == '\r' || **optionp == '\n') (*optionp)++; return -1; } |
|||||
↓ | scram_parse_server_first | 31 | 69 | 108 | ../../lib/scram/parser.c |
int scram_parse_server_first (const char *str, size_t len, struct scram_server_first *sf) { /* Minimum server first string is 'r=ab,s=biws,i=1'. */ if (strnlen (str, len) < 15) return -1; if (len == 0 || *str != 'r') return -1; str++, len--; if (len == 0 || *str != '=') return -1; str++, len--; { const char *p; size_t l; p = memchr (str, ',', len); if (!p) return -1; l = p - str; if (len < l) return -1; sf->nonce = malloc (l + 1); if (!sf->nonce) return -1; memcpy (sf->nonce, str, l); sf->nonce[l] = '\0'; str = p; len -= l; } if (len == 0 || *str != ',') return -1; str++, len--; if (len == 0 || *str != 's') return -1; str++, len--; if (len == 0 || *str != '=') return -1; str++, len--; { const char *p; size_t l; p = memchr (str, ',', len); if (!p) return -1; l = p - str; if (len < l) return -1; sf->salt = malloc (l + 1); if (!sf->salt) return -1; memcpy (sf->salt, str, l); sf->salt[l] = '\0'; str = p; len -= l; } if (len == 0 || *str != ',') return -1; str++, len--; if (len == 0 || *str != 'i') return -1; str++, len--; if (len == 0 || *str != '=') return -1; str++, len--; sf->iter = 0; for (; len > 0 && *str >= '0' && *str <= '9'; str++, len--) { size_t last_iter = sf->iter; sf->iter = sf->iter * 10 + (*str - '0'); /* Protect against wrap arounds. */ if (sf->iter < last_iter) return -1; } if (len > 0 && *str != ',') return -1; /* FIXME check that any extension fields follow valid syntax. */ if (scram_valid_server_first (sf) < 0) return -1; return 0; } |
|||||
↓ | parse_challenge | 29 | 95 | 203 | ../../lib/digest-md5/parser.c |
static int parse_challenge (char *challenge, digest_md5_challenge * out) { int done_algorithm = 0; int disable_qop_auth_conf = 0; char *value; memset (out, 0, sizeof (*out)); /* The size of a digest-challenge MUST be less than 2048 bytes. */ if (strlen (challenge) >= 2048) return -1; while (*challenge != '\0') switch (digest_md5_getsubopt (&challenge, digest_challenge_opts, &value)) { case CHALLENGE_REALM: { char **tmp; out->nrealms++; tmp = realloc (out->realms, out->nrealms * sizeof (*out->realms)); if (!tmp) return -1; out->realms = tmp; out->realms[out->nrealms - 1] = strdup (value); if (!out->realms[out->nrealms - 1]) return -1; } break; case CHALLENGE_NONCE: /* This directive is required and MUST appear exactly once; if not present, or if multiple instances are present, the client should abort the authentication exchange. */ if (out->nonce) return -1; out->nonce = strdup (value); if (!out->nonce) return -1; break; case CHALLENGE_QOP: /* < |
|||||
↓ | _gsasl_digest_md5_client_step | 27 | 91 | 185 | ../../lib/digest-md5/client.c |
int _gsasl_digest_md5_client_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { _Gsasl_digest_md5_client_state *state = mech_data; int rc, res; *output = NULL; *output_len = 0; switch (state->step) { case 0: state->step++; if (input_len == 0) return GSASL_NEEDS_MORE; /* fall through */ case 1: { if (digest_md5_parse_challenge (input, input_len, &state->challenge) < 0) return GSASL_MECHANISM_PARSE_ERROR; /* FIXME: How to let application know of remaining realms? One idea, add a GSASL_REALM_COUNT property, and have the GSASL_REALM be that many concatenated zero terminated realm strings. Slightly hackish, though. Another cleaner approach would be to add gsasl_property_set_array and gsasl_property_get_array APIs, for those properties that may be used multiple times. */ if (state->challenge.nrealms > 0) gsasl_property_set (sctx, GSASL_REALM, state->challenge.realms[0]); else gsasl_property_set (sctx, GSASL_REALM, NULL); /* FIXME: cipher, maxbuf. */ /* Create response token. */ state->response.utf8 = 1; gsasl_property_set (sctx, GSASL_QOPS, digest_md5_qops2qopstr (state->challenge.qops)); { const char *qop = gsasl_property_get (sctx, GSASL_QOP); if (!qop) state->response.qop = GSASL_QOP_AUTH; else if (strcmp (qop, "qop-int") == 0) state->response.qop = GSASL_QOP_AUTH_INT; else if (strcmp (qop, "qop-auth") == 0) state->response.qop = GSASL_QOP_AUTH; else /* We don't support confidentiality or unknown keywords. */ return GSASL_AUTHENTICATION_ERROR; } state->response.nonce = strdup (state->challenge.nonce); if (!state->response.nonce) return GSASL_MALLOC_ERROR; { const char *service = gsasl_property_get (sctx, GSASL_SERVICE); const char *hostname = gsasl_property_get (sctx, GSASL_HOSTNAME); if (!service) return GSASL_NO_SERVICE; if (!hostname) return GSASL_NO_HOSTNAME; if (asprintf (&state->response.digesturi, "%s/%s", service, hostname) < 0) return GSASL_MALLOC_ERROR; } { const char *c; char *tmp, *tmp2; c = gsasl_property_get (sctx, GSASL_AUTHID); if (!c) return GSASL_NO_AUTHID; state->response.username = strdup (c); if (!state->response.username) return GSASL_MALLOC_ERROR; c = gsasl_property_get (sctx, GSASL_AUTHZID); if (c) { state->response.authzid = strdup (c); if (!state->response.authzid) return GSASL_MALLOC_ERROR; } gsasl_callback (NULL, sctx, GSASL_REALM); c = gsasl_property_fast (sctx, GSASL_REALM); if (c) { state->response.realm = strdup (c); if (!state->response.realm) return GSASL_MALLOC_ERROR; } c = gsasl_property_get (sctx, GSASL_PASSWORD); if (!c) return GSASL_NO_PASSWORD; tmp2 = utf8tolatin1ifpossible (c); rc = asprintf (&tmp, "%s:%s:%s", state->response.username, state->response.realm ? state->response.realm : "", tmp2); free (tmp2); if (rc < 0) return GSASL_MALLOC_ERROR; rc = gsasl_md5 (tmp, strlen (tmp), &tmp2); free (tmp); if (rc != GSASL_OK) return rc; memcpy (state->secret, tmp2, DIGEST_MD5_LENGTH); free (tmp2); } rc = digest_md5_hmac (state->response.response, state->secret, state->response.nonce, state->response.nc, state->response.cnonce, state->response.qop, state->response.authzid, state->response.digesturi, 0, state->response.cipher, state->kic, state->kis, state->kcc, state->kcs); if (rc) return GSASL_CRYPTO_ERROR; *output = digest_md5_print_response (&state->response); if (!*output) return GSASL_AUTHENTICATION_ERROR; *output_len = strlen (*output); state->step++; res = GSASL_NEEDS_MORE; } break; case 2: { char check[DIGEST_MD5_RESPONSE_LENGTH + 1]; if (digest_md5_parse_finish (input, input_len, &state->finish) < 0) return GSASL_MECHANISM_PARSE_ERROR; res = digest_md5_hmac (check, state->secret, state->response.nonce, state->response.nc, state->response.cnonce, state->response.qop, state->response.authzid, state->response.digesturi, 1, state->response.cipher, NULL, NULL, NULL, NULL); if (res != GSASL_OK) break; if (strcmp (state->finish.rspauth, check) == 0) res = GSASL_OK; else res = GSASL_AUTHENTICATION_ERROR; state->step++; } break; default: res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; break; } return res; } |
|||||
↓ | _gsasl_digest_md5_server_step | 26 | 92 | 192 | ../../lib/digest-md5/server.c |
int _gsasl_digest_md5_server_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { _Gsasl_digest_md5_server_state *state = mech_data; int rc, res; *output = NULL; *output_len = 0; switch (state->step) { case 0: /* Set realm. */ { const char *c; c = gsasl_property_get (sctx, GSASL_REALM); if (c) { state->challenge.nrealms = 1; state->challenge.realms = malloc (sizeof (*state->challenge.realms)); if (!state->challenge.realms) return GSASL_MALLOC_ERROR; state->challenge.realms[0] = strdup (c); if (!state->challenge.realms[0]) return GSASL_MALLOC_ERROR; } } /* Set QOP */ { const char *qopstr = gsasl_property_get (sctx, GSASL_QOPS); if (qopstr) { int qops = digest_md5_qopstr2qops (qopstr); if (qops == -1) return GSASL_MALLOC_ERROR; /* We don't support confidentiality right now. */ if (qops & DIGEST_MD5_QOP_AUTH_CONF) return GSASL_AUTHENTICATION_ERROR; if (qops) state->challenge.qops = qops; } } /* FIXME: cipher, maxbuf, more realms. */ /* Create challenge. */ *output = digest_md5_print_challenge (&state->challenge); if (!*output) return GSASL_AUTHENTICATION_ERROR; *output_len = strlen (*output); state->step++; res = GSASL_NEEDS_MORE; break; case 1: if (digest_md5_parse_response (input, input_len, &state->response) < 0) return GSASL_MECHANISM_PARSE_ERROR; /* Make sure response is consistent with challenge. */ if (digest_md5_validate (&state->challenge, &state->response) < 0) return GSASL_MECHANISM_PARSE_ERROR; /* Store properties, from the client response. */ if (state->response.utf8) { gsasl_property_set (sctx, GSASL_AUTHID, state->response.username); gsasl_property_set (sctx, GSASL_REALM, state->response.realm); } else { /* Client provided username/realm in ISO-8859-1 form, convert it to UTF-8 since the library is all-UTF-8. */ char *tmp; tmp = latin1toutf8 (state->response.username); if (!tmp) return GSASL_MALLOC_ERROR; gsasl_property_set (sctx, GSASL_AUTHID, tmp); free (tmp); tmp = latin1toutf8 (state->response.realm); if (!tmp) return GSASL_MALLOC_ERROR; gsasl_property_set (sctx, GSASL_REALM, tmp); free (tmp); } gsasl_property_set (sctx, GSASL_AUTHZID, state->response.authzid); /* FIXME: cipher, maxbuf. */ /* Compute secret. */ { const char *passwd; const char *hashed_passwd; hashed_passwd = gsasl_property_get (sctx, GSASL_DIGEST_MD5_HASHED_PASSWORD); if (hashed_passwd) { if (strlen (hashed_passwd) != (DIGEST_MD5_LENGTH * 2)) return GSASL_AUTHENTICATION_ERROR; rc = _gsasl_digest_md5_set_hashed_secret (state->secret, hashed_passwd); if (rc != GSASL_OK) return rc; } else if ((passwd = gsasl_property_get (sctx, GSASL_PASSWORD)) != NULL) { char *tmp, *tmp2; tmp2 = utf8tolatin1ifpossible (passwd); rc = asprintf (&tmp, "%s:%s:%s", state->response.username, state->response.realm ? state->response.realm : "", tmp2); free (tmp2); if (rc < 0) return GSASL_MALLOC_ERROR; rc = gsasl_md5 (tmp, strlen (tmp), &tmp2); free (tmp); if (rc != GSASL_OK) return rc; memcpy (state->secret, tmp2, DIGEST_MD5_LENGTH); free (tmp2); } else { return GSASL_NO_PASSWORD; } } /* Check client response. */ { char check[DIGEST_MD5_RESPONSE_LENGTH + 1]; rc = digest_md5_hmac (check, state->secret, state->response.nonce, state->response.nc, state->response.cnonce, state->response.qop, state->response.authzid, state->response.digesturi, 0, state->response.cipher, state->kic, state->kis, state->kcc, state->kcs); if (rc) return GSASL_AUTHENTICATION_ERROR; if (strcmp (state->response.response, check) != 0) return GSASL_AUTHENTICATION_ERROR; } /* Create finish token. */ rc = digest_md5_hmac (state->finish.rspauth, state->secret, state->response.nonce, state->response.nc, state->response.cnonce, state->response.qop, state->response.authzid, state->response.digesturi, 1, state->response.cipher, NULL, NULL, NULL, NULL); if (rc) return GSASL_AUTHENTICATION_ERROR; *output = digest_md5_print_finish (&state->finish); if (!*output) return GSASL_MALLOC_ERROR; *output_len = strlen (*output); state->step++; res = GSASL_OK; break; default: res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; break; } return res; } |
|||||
↓ | _gsasl_gssapi_client_step | 22 | 91 | 178 | ../../lib/gssapi/client.c |
int _gsasl_gssapi_client_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { _Gsasl_gssapi_client_state *state = mech_data; char clientwrap[4]; gss_qop_t serverqop; gss_buffer_desc bufdesc, bufdesc2; gss_buffer_t buf = GSS_C_NO_BUFFER; OM_uint32 maj_stat, min_stat; int conf_state; int res; const char *p; if (state->service == NULL) { const char *service, *hostname; service = gsasl_property_get (sctx, GSASL_SERVICE); if (!service) return GSASL_NO_SERVICE; hostname = gsasl_property_get (sctx, GSASL_HOSTNAME); if (!hostname) return GSASL_NO_HOSTNAME; /* FIXME: Use asprintf. */ bufdesc.length = strlen (service) + 1 + strlen (hostname) + 1; bufdesc.value = malloc (bufdesc.length); if (bufdesc.value == NULL) return GSASL_MALLOC_ERROR; sprintf (bufdesc.value, "%s@%s", service, hostname); maj_stat = gss_import_name (&min_stat, &bufdesc, GSS_C_NT_HOSTBASED_SERVICE, &state->service); free (bufdesc.value); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_IMPORT_NAME_ERROR; } switch (state->step) { case 1: bufdesc.length = input_len; bufdesc.value = (void *) input; buf = &bufdesc; /* fall through */ case 0: bufdesc2.length = 0; bufdesc2.value = NULL; maj_stat = gss_init_sec_context (&min_stat, GSS_C_NO_CREDENTIAL, &state->context, state->service, GSS_C_NO_OID, GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG, 0, GSS_C_NO_CHANNEL_BINDINGS, buf, NULL, &bufdesc2, NULL, NULL); if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR; *output_len = bufdesc2.length; *output = malloc (*output_len); if (!*output) return GSASL_MALLOC_ERROR; memcpy (*output, bufdesc2.value, bufdesc2.length); if (maj_stat == GSS_S_COMPLETE) state->step = 2; else state->step = 1; maj_stat = gss_release_buffer (&min_stat, &bufdesc2); if (maj_stat != GSS_S_COMPLETE) return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; res = GSASL_NEEDS_MORE; break; case 2: /* [RFC 2222 section 7.2.1]: The client passes this token to GSS_Unwrap and interprets the first octet of resulting cleartext as a bit-mask specifying the security layers supported by the server and the second through fourth octets as the maximum size output_message to send to the server. The client then constructs data, with the first octet containing the bit-mask specifying the selected security layer, the second through fourth octets containing in network byte order the maximum size output_message the client is able to receive, and the remaining octets containing the authorization identity. The client passes the data to GSS_Wrap with conf_flag set to FALSE, and responds with the generated output_message. The client can then consider the server authenticated. */ bufdesc.length = input_len; bufdesc.value = (void *) input; maj_stat = gss_unwrap (&min_stat, state->context, &bufdesc, &bufdesc2, &conf_state, &serverqop); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_UNWRAP_ERROR; if (bufdesc2.length != 4) return GSASL_MECHANISM_PARSE_ERROR; memcpy (clientwrap, bufdesc2.value, 4); maj_stat = gss_release_buffer (&min_stat, &bufdesc2); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; #if 0 /* FIXME: Fix qop. */ if (cb_qop) state->qop = cb_qop (sctx, serverqop); if ((state->qop & serverqop) == 0) /* Server does not support what user wanted. */ return GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR; #endif /* FIXME: Fix maxbuf. */ p = gsasl_property_get (sctx, GSASL_AUTHID); if (!p) return GSASL_NO_AUTHID; bufdesc.length = 4 + strlen (p); bufdesc.value = malloc (bufdesc.length); if (!bufdesc.value) return GSASL_MALLOC_ERROR; { char *q = bufdesc.value; q[0] = state->qop; memcpy (q + 1, clientwrap + 1, 3); memcpy (q + 4, p, strlen (p)); } maj_stat = gss_wrap (&min_stat, state->context, 0, GSS_C_QOP_DEFAULT, &bufdesc, &conf_state, &bufdesc2); free (bufdesc.value); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_WRAP_ERROR; *output_len = bufdesc2.length; *output = malloc (bufdesc2.length); if (!*output) return GSASL_MALLOC_ERROR; memcpy (*output, bufdesc2.value, bufdesc2.length); maj_stat = gss_release_buffer (&min_stat, &bufdesc2); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; state->step++; res = GSASL_OK; break; default: res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; break; } return res; } |
|||||
↓ | _gsasl_gssapi_server_step | 20 | 75 | 153 | ../../lib/gssapi/server.c |
int _gsasl_gssapi_server_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { _Gsasl_gssapi_server_state *state = mech_data; gss_buffer_desc bufdesc1, bufdesc2; OM_uint32 maj_stat, min_stat; gss_buffer_desc client_name; gss_OID mech_type; char tmp[4]; int res; *output = NULL; *output_len = 0; switch (state->step) { case 0: if (input_len == 0) { res = GSASL_NEEDS_MORE; break; } state->step++; /* fall through */ case 1: bufdesc1.value = (void *) input; bufdesc1.length = input_len; if (state->client) { gss_release_name (&min_stat, &state->client); state->client = GSS_C_NO_NAME; } maj_stat = gss_accept_sec_context (&min_stat, &state->context, state->cred, &bufdesc1, GSS_C_NO_CHANNEL_BINDINGS, &state->client, &mech_type, &bufdesc2, NULL, NULL, NULL); if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) return GSASL_GSSAPI_ACCEPT_SEC_CONTEXT_ERROR; if (maj_stat == GSS_S_COMPLETE) state->step++; if (maj_stat == GSS_S_CONTINUE_NEEDED || bufdesc2.length > 0) { *output = malloc (bufdesc2.length); if (!*output) return GSASL_MALLOC_ERROR; memcpy (*output, bufdesc2.value, bufdesc2.length); *output_len = bufdesc2.length; } maj_stat = gss_release_buffer (&min_stat, &bufdesc2); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; if (maj_stat == GSS_S_CONTINUE_NEEDED || *output_len > 0) { res = GSASL_NEEDS_MORE; break; } /* fall through */ case 2: memset (tmp, 0xFF, 4); tmp[0] = GSASL_QOP_AUTH; bufdesc1.length = 4; bufdesc1.value = tmp; maj_stat = gss_wrap (&min_stat, state->context, 0, GSS_C_QOP_DEFAULT, &bufdesc1, NULL, &bufdesc2); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_WRAP_ERROR; *output = malloc (bufdesc2.length); if (!*output) return GSASL_MALLOC_ERROR; memcpy (*output, bufdesc2.value, bufdesc2.length); *output_len = bufdesc2.length; maj_stat = gss_release_buffer (&min_stat, &bufdesc2); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; state->step++; res = GSASL_NEEDS_MORE; break; case 3: bufdesc1.value = (void *) input; bufdesc1.length = input_len; maj_stat = gss_unwrap (&min_stat, state->context, &bufdesc1, &bufdesc2, NULL, NULL); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_UNWRAP_ERROR; /* [RFC 2222 section 7.2.1]: The client passes this token to GSS_Unwrap and interprets the first octet of resulting cleartext as a bit-mask specifying the security layers supported by the server and the second through fourth octets as the maximum size output_message to send to the server. The client then constructs data, with the first octet containing the bit-mask specifying the selected security layer, the second through fourth octets containing in network byte order the maximum size output_message the client is able to receive, and the remaining octets containing the authorization identity. The client passes the data to GSS_Wrap with conf_flag set to FALSE, and responds with the generated output_message. The client can then consider the server authenticated. */ if ((((char *) bufdesc2.value)[0] & GSASL_QOP_AUTH) == 0) { /* Integrity or privacy unsupported */ maj_stat = gss_release_buffer (&min_stat, &bufdesc2); return GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR; } gsasl_property_set_raw (sctx, GSASL_AUTHZID, (char *) bufdesc2.value + 4, bufdesc2.length - 4); maj_stat = gss_display_name (&min_stat, state->client, &client_name, &mech_type); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_DISPLAY_NAME_ERROR; gsasl_property_set_raw (sctx, GSASL_GSSAPI_DISPLAY_NAME, client_name.value, client_name.length); maj_stat = gss_release_buffer (&min_stat, &bufdesc2); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_GSSAPI); state->step++; break; default: res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; break; } return res; } |
|||||
↓ | _gsasl_openid20_server_step | 17 | 61 | 125 | ../../lib/openid20/server.c |
int _gsasl_openid20_server_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { struct openid20_server_state *state = mech_data; int res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; *output_len = 0; *output = NULL; switch (state->step) { case 0: { const char *p; char *authzid; size_t headerlen; if (input_len == 0) return GSASL_NEEDS_MORE; res = _gsasl_parse_gs2_header (input, input_len, &authzid, &headerlen); if (res != GSASL_OK) return res; if (authzid) { gsasl_property_set (sctx, GSASL_AUTHZID, authzid); free (authzid); } input += headerlen; input_len -= headerlen; gsasl_property_set_raw (sctx, GSASL_AUTHID, input, input_len); p = gsasl_property_get (sctx, GSASL_OPENID20_REDIRECT_URL); if (!p || !*p) return GSASL_NO_OPENID20_REDIRECT_URL; *output_len = strlen (p); *output = malloc (*output_len); if (!*output) return GSASL_MALLOC_ERROR; memcpy (*output, p, *output_len); res = GSASL_NEEDS_MORE; state->step++; break; } case 1: { const char *outcome_data; if (!(input_len == 1 && *input == '=')) return GSASL_MECHANISM_PARSE_ERROR; res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_OPENID20); if (res != GSASL_OK) { *output = strdup ("openid.error=fail"); if (!*output) return GSASL_MALLOC_ERROR; *output_len = strlen (*output); /* [RFC4422] Section 3.6 explicitly prohibits additional information in an unsuccessful authentication outcome. Therefore, the openid.error and openid.error_code are to be sent as an additional challenge in the event of an unsuccessful outcome. In this case, as the protocol is lock step, the client will follow with an additional exchange containing "=", after which the server will respond with an application-level outcome. */ state->allow_error_step = 1; state->step++; return GSASL_NEEDS_MORE; } outcome_data = gsasl_property_get (sctx, GSASL_OPENID20_OUTCOME_DATA); if (outcome_data) { *output = strdup (outcome_data); if (!*output) return GSASL_MALLOC_ERROR; *output_len = strlen (*output); } else { *output = NULL; *output_len = 0; } res = GSASL_OK; state->step++; } break; case 2: { /* We only get here when the previous step signalled an error to the client. */ if (!state->allow_error_step) return GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; if (!(input_len == 1 && *input == '=')) return GSASL_MECHANISM_PARSE_ERROR; res = GSASL_AUTHENTICATION_ERROR; state->step++; } break; default: break; } return res; } |
|||||
↓ | _gsasl_gs2_server_step | 16 | 65 | 126 | ../../lib/gs2/server.c |
int _gsasl_gs2_server_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { _Gsasl_gs2_server_state *state = mech_data; gss_buffer_desc bufdesc1, bufdesc2; OM_uint32 maj_stat, min_stat; gss_buffer_desc client_name; gss_OID mech_type; int res; OM_uint32 ret_flags; int free_bufdesc1 = 0; *output = NULL; *output_len = 0; bufdesc1.value = input; bufdesc1.length = input_len; switch (state->step) { case 0: if (input_len == 0) { res = GSASL_NEEDS_MORE; break; } state->step++; /* fall through */ case 1: { char *authzid; size_t headerlen; res = _gsasl_parse_gs2_header (input, input_len, &authzid, &headerlen); if (res != GSASL_OK) return res; if (authzid) { gsasl_property_set (sctx, GSASL_AUTHZID, authzid); free (authzid); } state->cb.application_data.value = input; state->cb.application_data.length = headerlen; bufdesc2.value = input + headerlen; bufdesc2.length = input_len - headerlen; maj_stat = gss_encapsulate_token (&bufdesc2, state->mech_oid, &bufdesc1); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_ENCAPSULATE_TOKEN_ERROR; free_bufdesc1 = 1; } state->step++; /* fall through */ case 2: if (state->client) { gss_release_name (&min_stat, &state->client); state->client = GSS_C_NO_NAME; } maj_stat = gss_accept_sec_context (&min_stat, &state->context, state->cred, &bufdesc1, &state->cb, &state->client, &mech_type, &bufdesc2, &ret_flags, NULL, NULL); if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) return GSASL_GSSAPI_ACCEPT_SEC_CONTEXT_ERROR; if (maj_stat == GSS_S_COMPLETE) { state->step++; if (!(ret_flags & GSS_C_MUTUAL_FLAG)) return GSASL_MECHANISM_PARSE_ERROR; maj_stat = gss_display_name (&min_stat, state->client, &client_name, &mech_type); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_DISPLAY_NAME_ERROR; gsasl_property_set_raw (sctx, GSASL_GSSAPI_DISPLAY_NAME, client_name.value, client_name.length); res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_GSSAPI); } else res = GSASL_NEEDS_MORE; if (free_bufdesc1) { maj_stat = gss_release_buffer (&min_stat, &bufdesc1); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; } *output = malloc (bufdesc2.length); if (!*output) return GSASL_MALLOC_ERROR; memcpy (*output, bufdesc2.value, bufdesc2.length); *output_len = bufdesc2.length; maj_stat = gss_release_buffer (&min_stat, &bufdesc2); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; break; default: res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; break; } return res; } |
|||||
↓ | _gsasl_securid_client_step | 16 | 59 | 106 | ../../lib/securid/client.c |
int _gsasl_securid_client_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { int *step = mech_data; const char *authzid = NULL, *authid = NULL, *passcode = NULL, *pin = NULL; size_t authzidlen, authidlen, passcodelen, pinlen = 0; int do_pin = 0; int res; switch (*step) { case 1: if (input_len == strlen (PASSCODE) && memcmp (input, PASSCODE, strlen (PASSCODE)) == 0) { *step = 0; } else if (input_len >= strlen (PIN) && memcmp (input, PIN, strlen (PIN)) == 0) { do_pin = 1; *step = 0; } else { *output_len = 0; res = GSASL_OK; break; } /* fall through */ case 0: authzid = gsasl_property_get (sctx, GSASL_AUTHZID); if (authzid) authzidlen = strlen (authzid); else authzidlen = 0; authid = gsasl_property_get (sctx, GSASL_AUTHID); if (!authid) return GSASL_NO_AUTHID; authidlen = strlen (authid); passcode = gsasl_property_get (sctx, GSASL_PASSCODE); if (!passcode) return GSASL_NO_PASSCODE; passcodelen = strlen (passcode); if (do_pin) { if (input_len > strlen (PIN)) gsasl_property_set_raw (sctx, GSASL_SUGGESTED_PIN, &input[strlen (PIN)], input_len - strlen (PIN)); pin = gsasl_property_get (sctx, GSASL_PIN); if (!pin) return GSASL_NO_PIN; pinlen = strlen (pin); } *output_len = authzidlen + 1 + authidlen + 1 + passcodelen + 1; if (do_pin) *output_len += pinlen + 1; *output = malloc (*output_len); if (*output == NULL) return GSASL_MALLOC_ERROR; if (authzid) memcpy (*output, authzid, authzidlen); (*output)[authzidlen] = '\0'; memcpy (*output + authzidlen + 1, authid, authidlen); (*output)[authzidlen + 1 + authidlen] = '\0'; memcpy (*output + authzidlen + 1 + authidlen + 1, passcode, passcodelen); (*output)[authzidlen + 1 + authidlen + 1 + passcodelen] = '\0'; if (do_pin) { memcpy (*output + authzidlen + 1 + authidlen + 1 + passcodelen + 1, pin, pinlen); (*output)[authzidlen + 1 + authidlen + 1 + passcodelen + 1 + pinlen] = '\0'; } (*step)++; res = GSASL_OK; break; case 2: *output_len = 0; *output = NULL; (*step)++; res = GSASL_OK; break; default: res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; break; } return res; } |
|||||
↓ | scram_valid_client_first | 15 | 19 | 46 | ../../lib/scram/validate.c |
bool scram_valid_client_first (struct scram_client_first *cf) { /* Check that cbflag is one of permitted values. */ switch (cf->cbflag) { case 'p': case 'n': case 'y': break; default: return false; } /* Check that cbname is only set when cbflag is p. */ if (cf->cbflag == 'p' && cf->cbname == NULL) return false; else if (cf->cbflag != 'p' && cf->cbname != NULL) return false; if (cf->cbname) { const char *p = cf->cbname; while (*p && strchr ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789.-", *p)) p++; if (*p) return false; } /* We require a non-zero username string. */ if (cf->username == NULL || *cf->username == '\0') return false; /* We require a non-zero client nonce. */ if (cf->client_nonce == NULL || *cf->client_nonce == '\0') return false; /* Nonce cannot contain ','. */ if (strchr (cf->client_nonce, ',')) return false; return true; } |
|||||
↓ | register_builtin_mechs | 15 | 44 | 89 | ../../lib/src/init.c |
static int register_builtin_mechs (Gsasl * ctx) { int rc = GSASL_OK; #ifdef USE_ANONYMOUS rc = gsasl_register (ctx, &gsasl_anonymous_mechanism); if (rc != GSASL_OK) return rc; #endif /* USE_ANONYMOUS */ #ifdef USE_EXTERNAL rc = gsasl_register (ctx, &gsasl_external_mechanism); if (rc != GSASL_OK) return rc; #endif /* USE_EXTERNAL */ #ifdef USE_LOGIN rc = gsasl_register (ctx, &gsasl_login_mechanism); if (rc != GSASL_OK) return rc; #endif /* USE_LOGIN */ #ifdef USE_PLAIN rc = gsasl_register (ctx, &gsasl_plain_mechanism); if (rc != GSASL_OK) return rc; #endif /* USE_PLAIN */ #ifdef USE_SECURID rc = gsasl_register (ctx, &gsasl_securid_mechanism); if (rc != GSASL_OK) return rc; #endif /* USE_SECURID */ #ifdef USE_NTLM rc = gsasl_register (ctx, &gsasl_ntlm_mechanism); if (rc != GSASL_OK) return rc; #endif /* USE_NTLM */ #ifdef USE_DIGEST_MD5 rc = gsasl_register (ctx, &gsasl_digest_md5_mechanism); if (rc != GSASL_OK) return rc; #endif /* USE_DIGEST_MD5 */ #ifdef USE_CRAM_MD5 rc = gsasl_register (ctx, &gsasl_cram_md5_mechanism); if (rc != GSASL_OK) return rc; #endif /* USE_CRAM_MD5 */ #ifdef USE_SCRAM_SHA1 rc = gsasl_register (ctx, &gsasl_scram_sha1_mechanism); if (rc != GSASL_OK) return rc; rc = gsasl_register (ctx, &gsasl_scram_sha1_plus_mechanism); if (rc != GSASL_OK) return rc; #endif /* USE_SCRAM_SHA1 */ #ifdef USE_SAML20 rc = gsasl_register (ctx, &gsasl_saml20_mechanism); if (rc != GSASL_OK) return rc; #endif /* USE_SAML20 */ #ifdef USE_OPENID20 rc = gsasl_register (ctx, &gsasl_openid20_mechanism); if (rc != GSASL_OK) return rc; #endif /* USE_OPENID20 */ #ifdef USE_GSSAPI rc = gsasl_register (ctx, &gsasl_gssapi_mechanism); if (rc != GSASL_OK) return rc; #endif /* USE_GSSAPI */ #ifdef USE_GS2 rc = gsasl_register (ctx, &gsasl_gs2_krb5_mechanism); if (rc != GSASL_OK) return rc; #endif /* USE_GSSAPI */ return GSASL_OK; } |
|||||
↓ | _gsasl_securid_server_step | 14 | 55 | 89 | ../../lib/securid/server.c |
int _gsasl_securid_server_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { const char *authorization_id = NULL; const char *authentication_id = NULL; const char *passcode = NULL; const char *suggestedpin; char *pin = NULL; int res; size_t len; if (input_len == 0) { *output_len = 0; *output = NULL; return GSASL_NEEDS_MORE; } authorization_id = input; authentication_id = memchr (input, '\0', input_len - 1); if (authentication_id) { authentication_id++; passcode = memchr (authentication_id, '\0', input_len - strlen (authorization_id) - 1 - 1); if (passcode) { passcode++; pin = memchr (passcode, '\0', input_len - strlen (authorization_id) - 1 - strlen (authentication_id) - 1 - 1); if (pin) { pin++; if (pin && !*pin) pin = NULL; } } } if (passcode == NULL) return GSASL_MECHANISM_PARSE_ERROR; gsasl_property_set (sctx, GSASL_AUTHID, authentication_id); gsasl_property_set (sctx, GSASL_AUTHZID, authorization_id); gsasl_property_set (sctx, GSASL_PASSCODE, passcode); if (pin) gsasl_property_set (sctx, GSASL_PIN, pin); else gsasl_property_set (sctx, GSASL_PIN, NULL); res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_SECURID); switch (res) { case GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE: *output = strdup (PASSCODE); if (!*output) return GSASL_MALLOC_ERROR; *output_len = strlen (PASSCODE); res = GSASL_NEEDS_MORE; break; case GSASL_SECURID_SERVER_NEED_NEW_PIN: suggestedpin = gsasl_property_get (sctx, GSASL_SUGGESTED_PIN); if (suggestedpin) len = strlen (suggestedpin); else len = 0; *output_len = strlen (PIN) + len; *output = malloc (*output_len); if (!*output) return GSASL_MALLOC_ERROR; memcpy (*output, PIN, strlen (PIN)); if (suggestedpin) memcpy (*output + strlen (PIN), suggestedpin, len); res = GSASL_NEEDS_MORE; break; default: *output_len = 0; *output = NULL; break; } return res; } |
|||||
↓ | unescape_authzid | 14 | 24 | 43 | ../../lib/src/mechtools.c |
static int unescape_authzid (const char *str, size_t len, char **authzid) { char *p; if (memchr (str, ',', len) != NULL) return GSASL_MECHANISM_PARSE_ERROR; p = *authzid = malloc (len + 1); if (!p) return GSASL_MALLOC_ERROR; while (len > 0 && *str) { if (len >= 3 && str[0] == '=' && str[1] == '2' && str[2] == 'C') { *p++ = ','; str += 3; len -= 3; } else if (len >= 3 && str[0] == '=' && str[1] == '3' && str[2] == 'D') { *p++ = '='; str += 3; len -= 3; } else if (str[0] == '=') { free (*authzid); *authzid = NULL; return GSASL_MECHANISM_PARSE_ERROR; } else { *p++ = *str; str++; len--; } } *p = '\0'; return GSASL_OK; } |
|||||
↓ | _gsasl_login_server_step | 13 | 50 | 87 | ../../lib/login/server.c |
int _gsasl_login_server_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { struct _Gsasl_login_server_state *state = mech_data; int res; switch (state->step) { case 0: *output = strdup (CHALLENGE_USERNAME); if (!*output) return GSASL_MALLOC_ERROR; *output_len = strlen (CHALLENGE_USERNAME); state->step++; res = GSASL_NEEDS_MORE; break; case 1: if (input_len == 0) return GSASL_MECHANISM_PARSE_ERROR; state->username = malloc (input_len + 1); if (state->username == NULL) return GSASL_MALLOC_ERROR; memcpy (state->username, input, input_len); state->username[input_len] = '\0'; *output = strdup (CHALLENGE_PASSWORD); if (!*output) return GSASL_MALLOC_ERROR; *output_len = strlen (CHALLENGE_PASSWORD); state->step++; res = GSASL_NEEDS_MORE; break; case 2: if (input_len == 0) return GSASL_MECHANISM_PARSE_ERROR; state->password = malloc (input_len + 1); if (state->password == NULL) return GSASL_MALLOC_ERROR; memcpy (state->password, input, input_len); state->password[input_len] = '\0'; if (input_len != strlen (state->password)) return GSASL_MECHANISM_PARSE_ERROR; gsasl_property_set (sctx, GSASL_AUTHID, state->username); gsasl_property_set (sctx, GSASL_PASSWORD, state->password); res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_SIMPLE); if (res == GSASL_NO_CALLBACK) { const char *key; gsasl_property_set (sctx, GSASL_AUTHZID, NULL); gsasl_property_set (sctx, GSASL_PASSWORD, NULL); key = gsasl_property_get (sctx, GSASL_PASSWORD); if (key && strlen (state->password) == strlen (key) && strcmp (state->password, key) == 0) res = GSASL_OK; else res = GSASL_AUTHENTICATION_ERROR; } *output_len = 0; *output = NULL; state->step++; break; default: res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; break; } return res; } |
|||||
↓ | _gsasl_plain_server_step | 13 | 59 | 114 | ../../lib/plain/server.c |
int _gsasl_plain_server_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { const char *authzidptr = input; char *authidptr = NULL; char *passwordptr = NULL; char *passwdz = NULL, *passprep = NULL, *authidprep = NULL; int res; *output_len = 0; *output = NULL; if (input_len == 0) return GSASL_NEEDS_MORE; /* Parse input. */ { size_t tmplen; authidptr = memchr (input, 0, input_len - 1); if (authidptr) { authidptr++; passwordptr = memchr (authidptr, 0, input_len - strlen (input) - 1); if (passwordptr) passwordptr++; else return GSASL_MECHANISM_PARSE_ERROR; } else return GSASL_MECHANISM_PARSE_ERROR; /* As the NUL (U+0000) character is used as a deliminator, the NUL (U+0000) character MUST NOT appear in authzid, authcid, or passwd productions. */ tmplen = input_len - (size_t) (passwordptr - input); if (memchr (passwordptr, 0, tmplen)) return GSASL_MECHANISM_PARSE_ERROR; } /* Store authid, after preparing it... */ { res = gsasl_saslprep (authidptr, GSASL_ALLOW_UNASSIGNED, &authidprep, NULL); if (res != GSASL_OK) return res; gsasl_property_set (sctx, GSASL_AUTHID, authidprep); /* Store authzid, if absent, use SASLprep(authcid). */ if (*authzidptr == '\0') gsasl_property_set (sctx, GSASL_AUTHZID, authidprep); else gsasl_property_set (sctx, GSASL_AUTHZID, authzidptr); free (authidprep); } /* Store passwd, after preparing it... */ { size_t passwdzlen = input_len - (size_t) (passwordptr - input); /* Need to zero terminate password... */ passwdz = malloc (passwdzlen + 1); if (passwdz == NULL) return GSASL_MALLOC_ERROR; memcpy (passwdz, passwordptr, passwdzlen); passwdz[passwdzlen] = '\0'; res = gsasl_saslprep (passwdz, GSASL_ALLOW_UNASSIGNED, &passprep, NULL); free (passwdz); if (res != GSASL_OK) return res; gsasl_property_set (sctx, GSASL_PASSWORD, passprep); } /* Authorization. Let application verify credentials internally, but fall back to deal with it locally... */ res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_SIMPLE); if (res == GSASL_NO_CALLBACK) { const char *key; char *normkey; gsasl_property_set (sctx, GSASL_PASSWORD, NULL); key = gsasl_property_get (sctx, GSASL_PASSWORD); if (!key) { free (passprep); return GSASL_NO_PASSWORD; } /* Unassigned code points are not permitted. */ res = gsasl_saslprep (key, 0, &normkey, NULL); if (res != GSASL_OK) { free (passprep); return res; } if (strcmp (normkey, passprep) == 0) res = GSASL_OK; else res = GSASL_AUTHENTICATION_ERROR; free (normkey); } free (passprep); return res; } |
|||||
↓ | _gsasl_gs2_client_step | 13 | 37 | 75 | ../../lib/gs2/client.c |
int _gsasl_gs2_client_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { _gsasl_gs2_client_state *state = mech_data; gss_buffer_desc bufdesc; gss_buffer_t buf = GSS_C_NO_BUFFER; OM_uint32 maj_stat, min_stat, ret_flags; gss_OID actual_mech_type; int res; if (state->step > 2) return GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; if (state->step == 0) { res = prepare (sctx, state); if (res != GSASL_OK) return res; state->step++; } if (state->step == 2) { bufdesc.length = input_len; bufdesc.value = (void *) input; buf = &bufdesc; } /* First release memory for token from last round-trip, if any. */ if (state->token.value != NULL) { maj_stat = gss_release_buffer (&min_stat, &state->token); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; state->token.value = NULL; state->token.length = 0; } maj_stat = gss_init_sec_context (&min_stat, GSS_C_NO_CREDENTIAL, &state->context, state->service, state->mech_oid, GSS_C_MUTUAL_FLAG, 0, &state->cb, buf, &actual_mech_type, &state->token, &ret_flags, NULL); if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR; res = token2output (sctx, state, &state->token, output, output_len); if (res != GSASL_OK) return res; if (maj_stat == GSS_S_CONTINUE_NEEDED) return GSASL_NEEDS_MORE; /* The GSS-API layer is done here, check that we established a valid security context for GS2 purposes. */ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) return GSASL_AUTHENTICATION_ERROR; if (!gss_oid_equal (state->mech_oid, actual_mech_type)) return GSASL_AUTHENTICATION_ERROR; state->step++; return GSASL_OK; } |
|||||
↓ | digest_md5_decode | 12 | 40 | 76 | ../../lib/digest-md5/session.c |
int digest_md5_decode (const char *input, size_t input_len, char **output, size_t * output_len, digest_md5_qop qop, unsigned long readseqnum, char key[DIGEST_MD5_LENGTH]) { if (qop & DIGEST_MD5_QOP_AUTH_CONF) { return -1; } else if (qop & DIGEST_MD5_QOP_AUTH_INT) { char *seqnumin; char hash[GC_MD5_DIGEST_SIZE]; unsigned long len; char tmpbuf[SASL_INTEGRITY_PREFIX_LENGTH]; int res; if (input_len < SASL_INTEGRITY_PREFIX_LENGTH) return -2; len = C2I (input); if (input_len < SASL_INTEGRITY_PREFIX_LENGTH + len) return -2; len -= MAC_HMAC_LEN + MAC_MSG_TYPE_LEN + MAC_SEQNUM_LEN; seqnumin = malloc (SASL_INTEGRITY_PREFIX_LENGTH + len); if (seqnumin == NULL) return -1; tmpbuf[0] = (readseqnum >> 24) & 0xFF; tmpbuf[1] = (readseqnum >> 16) & 0xFF; tmpbuf[2] = (readseqnum >> 8) & 0xFF; tmpbuf[3] = readseqnum & 0xFF; memcpy (seqnumin, tmpbuf, SASL_INTEGRITY_PREFIX_LENGTH); memcpy (seqnumin + SASL_INTEGRITY_PREFIX_LENGTH, input + MAC_DATA_LEN, len); res = gc_hmac_md5 (key, MD5LEN, seqnumin, MAC_SEQNUM_LEN + len, hash); free (seqnumin); if (res) return -1; if (memcmp (hash, input + input_len - MAC_SEQNUM_LEN - MAC_MSG_TYPE_LEN - MAC_HMAC_LEN, MAC_HMAC_LEN) == 0 && memcmp (MAC_MSG_TYPE, input + input_len - MAC_SEQNUM_LEN - MAC_MSG_TYPE_LEN, MAC_MSG_TYPE_LEN) == 0 && memcmp (tmpbuf, input + input_len - MAC_SEQNUM_LEN, MAC_SEQNUM_LEN) == 0) { *output_len = len; *output = malloc (*output_len); if (!*output) return -1; memcpy (*output, input + MAC_DATA_LEN, len); } else return -1; } else { *output_len = input_len; *output = malloc (input_len); if (!*output) return -1; memcpy (*output, input, input_len); } return 0; } |
|||||
↓ | _gsasl_gs2_generate_header | 12 | 27 | 51 | ../../lib/src/mechtools.c |
int _gsasl_gs2_generate_header (bool nonstd, char cbflag, const char *cbname, const char *authzid, size_t extralen, const char *extra, char **gs2h, size_t * gs2hlen) { int elen = extralen; char *gs2cbflag; int len; if (cbflag == 'p') len = asprintf (&gs2cbflag, "p=%s", cbname); else if (cbflag == 'n') len = asprintf (&gs2cbflag, "n"); else if (cbflag == 'y') len = asprintf (&gs2cbflag, "y"); else /* internal caller error */ return GSASL_MECHANISM_PARSE_ERROR; if (len <= 0 || gs2cbflag == NULL) return GSASL_MALLOC_ERROR; if (authzid) { char *escaped_authzid = escape_authzid (authzid); if (!escaped_authzid) { free (gs2cbflag); return GSASL_MALLOC_ERROR; } len = asprintf (gs2h, "%s%s,a=%s,%.*s", nonstd ? "F," : "", gs2cbflag, escaped_authzid, elen, extra); free (escaped_authzid); } else len = asprintf (gs2h, "%s%s,,%.*s", nonstd ? "F," : "", gs2cbflag, elen, extra); free (gs2cbflag); if (len <= 0 || gs2h == NULL) return GSASL_MALLOC_ERROR; *gs2hlen = len; return GSASL_OK; } |
|||||
↓ | digest_md5_validate_response | 12 | 19 | 49 | ../../lib/digest-md5/validate.c |
int digest_md5_validate_response (digest_md5_response * r) { /* This directive is required and MUST be present exactly once; otherwise, authentication fails. */ if (!r->username) return -1; /* This directive is required and MUST be present exactly once; otherwise, authentication fails. */ if (!r->nonce) return -1; /* This directive is required and MUST be present exactly once; otherwise, authentication fails. */ if (!r->cnonce) return -1; /* This directive is required and MUST be present exactly once; otherwise, or if the value is 0, authentication fails. */ if (!r->nc) return -1; /* This directive is required and MUST be present exactly once; if multiple instances are present, the client MUST abort the authentication exchange. */ if (!r->digesturi) return -1; /* This directive is required and MUST be present exactly once; otherwise, authentication fails. */ if (!*r->response) return -1; if (strlen (r->response) != DIGEST_MD5_RESPONSE_LENGTH) return -1; /* This directive MUST appear exactly once if "auth-conf" is negotiated; if required and not present, authentication fails. If the client recognizes no cipher and the server only advertised "auth-conf" in the qop option, the client MUST abort the authentication exchange. */ if (r->qop == DIGEST_MD5_QOP_AUTH_CONF && !r->cipher) return -1; if (r->qop != DIGEST_MD5_QOP_AUTH_CONF && r->cipher) return -1; return 0; } |
|||||
↓ | unescape | 12 | 18 | 34 | ../../lib/scram/parser.c |
static char * unescape (const char *str, size_t len) { char *out = malloc (len + 1); char *p = out; if (!out) return NULL; while (len > 0 && *str) { if (len >= 3 && str[0] == '=' && str[1] == '2' && str[2] == 'C') { *p++ = ','; str += 3; len -= 3; } else if (len >= 3 && str[0] == '=' && str[1] == '3' && str[2] == 'D') { *p++ = '='; str += 3; len -= 3; } else { *p++ = *str; str++; len--; } } *p = '\0'; return out; } |
|||||
↓ | digest_md5_validate | 12 | 15 | 26 | ../../lib/digest-md5/validate.c |
int digest_md5_validate (digest_md5_challenge * c, digest_md5_response * r) { if (!c->nonce || !r->nonce) return -1; if (strcmp (c->nonce, r->nonce) != 0) return -1; if (r->nc != 1) return -1; if (!c->utf8 && r->utf8) return -1; if (!((c->qops ? c->qops : DIGEST_MD5_QOP_AUTH) & (r->qop ? r->qop : DIGEST_MD5_QOP_AUTH))) return -1; if ((r->qop & DIGEST_MD5_QOP_AUTH_CONF) && !(c->ciphers & r->cipher)) return -1; /* FIXME: Check more? */ return 0; } |
|||||
↓ | _gsasl_saml20_server_step | 11 | 41 | 79 | ../../lib/saml20/server.c |
int _gsasl_saml20_server_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { struct saml20_server_state *state = mech_data; int res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; *output_len = 0; *output = NULL; switch (state->step) { case 0: { const char *p; char *authzid; size_t headerlen; if (input_len == 0) return GSASL_NEEDS_MORE; res = _gsasl_parse_gs2_header (input, input_len, &authzid, &headerlen); if (res != GSASL_OK) return res; if (authzid) { gsasl_property_set (sctx, GSASL_AUTHZID, authzid); free (authzid); } input += headerlen; input_len -= headerlen; gsasl_property_set_raw (sctx, GSASL_SAML20_IDP_IDENTIFIER, input, input_len); p = gsasl_property_get (sctx, GSASL_SAML20_REDIRECT_URL); if (!p || !*p) return GSASL_NO_SAML20_REDIRECT_URL; *output_len = strlen (p); *output = malloc (*output_len); if (!*output) return GSASL_MALLOC_ERROR; memcpy (*output, p, *output_len); res = GSASL_NEEDS_MORE; state->step++; break; } case 1: { if (!(input_len == 1 && *input == '=')) return GSASL_MECHANISM_PARSE_ERROR; res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_SAML20); if (res != GSASL_OK) return res; *output = NULL; *output_len = 0; res = GSASL_OK; state->step++; break; } default: break; } return res; } |
|||||
↓ | scram_print_client_first | 11 | 22 | 40 | ../../lib/scram/printer.c |
int scram_print_client_first (struct scram_client_first *cf, char **out) { char *username = NULL; char *authzid = NULL; int n; /* Below we assume fields are sensible, so first verify that to avoid crashes. */ if (!scram_valid_client_first (cf)) return -1; /* Escape username and authzid. */ username = scram_escape (cf->username); if (!username) return -2; if (cf->authzid) { authzid = scram_escape (cf->authzid); if (!authzid) return -2; } n = asprintf (out, "%c%s%s,%s%s,n=%s,r=%s", cf->cbflag, cf->cbflag == 'p' ? "=" : "", cf->cbflag == 'p' ? cf->cbname : "", authzid ? "a=" : "", authzid ? authzid : "", username, cf->client_nonce); free (username); free (authzid); if (n <= 0 || *out == NULL) return -1; return 0; } |
|||||
_gsasl_openid20_client_step | 10 | 37 | 101 | ../../lib/openid20/client.c | |
_gsasl_ntlm_client_step | 10 | 53 | 105 | ../../lib/ntlm/ntlm.c | |
gs2_get_cred | 10 | 35 | 60 | ../../lib/gs2/server.c | |
scram_start | 10 | 34 | 54 | ../../lib/scram/server.c | |
gsasl_simple_getpass | 10 | 27 | 50 | ../../lib/src/md5pwd.c | |
prepare | 10 | 27 | 50 | ../../lib/gs2/client.c | |
utf8tolatin1ifpossible | 10 | 23 | 39 | ../../lib/digest-md5/nonascii.c | |
scram_valid_client_final | 10 | 13 | 29 | ../../lib/scram/validate.c | |
_gsasl_gssapi_client_encode | 9 | 28 | 54 | ../../lib/gssapi/client.c | |
gsasl_saslprep | 9 | 26 | 50 | ../../lib/src/saslprep.c | |
gsasl_client_suggest_mechanism | 9 | 25 | 45 | ../../lib/src/suggest.c | |
scram_parse_server_final | 9 | 18 | 32 | ../../lib/scram/parser.c | |
_gsasl_cram_md5_server_step | 8 | 34 | 62 | ../../lib/cram-md5/server.c | |
scram_start | 8 | 29 | 52 | ../../lib/scram/client.c | |
_gsasl_gssapi_client_decode | 8 | 27 | 52 | ../../lib/gssapi/client.c | |
setup | 8 | 22 | 40 | ../../lib/src/xstart.c | |
scram_valid_server_first | 8 | 11 | 24 | ../../lib/scram/validate.c | |
_gsasl_saml20_client_step | 7 | 25 | 57 | ../../lib/saml20/client.c | |
digest_md5_encode | 7 | 45 | 68 | ../../lib/digest-md5/session.c | |
_gsasl_cram_md5_client_step | 7 | 37 | 66 | ../../lib/cram-md5/client.c | |
_gsasl_gssapi_server_start | 7 | 36 | 61 | ../../lib/gssapi/server.c | |
gsasl_finish | 7 | 30 | 44 | ../../lib/src/xfinish.c | |
comma_append | 7 | 18 | 31 | ../../lib/digest-md5/printer.c | |
_gsasl_parse_gs2_header | 7 | 16 | 33 | ../../lib/src/mechtools.c | |
gsasl_register | 7 | 16 | 37 | ../../lib/src/register.c | |
parse_finish | 7 | 15 | 34 | ../../lib/digest-md5/parser.c | |
digest_md5_validate_challenge | 6 | 7 | 18 | ../../lib/digest-md5/validate.c | |
_gsasl_plain_client_step | 6 | 26 | 47 | ../../lib/plain/client.c | |
token2output | 6 | 23 | 44 | ../../lib/gs2/client.c | |
_gsasl_listmech | 6 | 20 | 35 | ../../lib/src/listmech.c | |
gsasl_done | 6 | 17 | 28 | ../../lib/src/done.c | |
gsasl_step64 | 6 | 15 | 31 | ../../lib/src/xstep.c | |
digest_md5_qopstr2qops | 5 | 22 | 54 | ../../lib/digest-md5/qop.c | |
gsasl_callback | 5 | 8 | 18 | ../../lib/src/callback.c | |
_gsasl_digest_md5_hexdigit_to_char | 5 | 5 | 13 | ../../lib/digest-md5/server.c | |
hexdigit_to_char | 5 | 5 | 9 | ../../lib/scram/client.c | |
escape_authzid | 5 | 16 | 32 | ../../lib/gs2/client.c | |
scram_escape | 5 | 16 | 32 | ../../lib/scram/printer.c | |
escape_authzid | 5 | 16 | 32 | ../../lib/src/mechtools.c | |
latin1toutf8 | 5 | 15 | 27 | ../../lib/digest-md5/nonascii.c | |
_gsasl_gs2_client_finish | 5 | 12 | 20 | ../../lib/gs2/client.c | |
_gsasl_gs2_server_finish | 5 | 11 | 20 | ../../lib/gs2/server.c | |
_gsasl_gssapi_server_finish | 5 | 11 | 20 | ../../lib/gssapi/server.c | |
_gsasl_login_client_step | 4 | 22 | 43 | ../../lib/login/client.c | |
_gsasl_gssapi_client_finish | 4 | 9 | 17 | ../../lib/gssapi/client.c | |
find_mechanism | 4 | 9 | 14 | ../../lib/src/xstart.c | |
gsasl_strerror | 4 | 9 | 17 | ../../lib/src/error.c | |
gsasl_property_set_raw | 4 | 9 | 22 | ../../lib/src/property.c | |
_gsasl_anonymous_server_step | 4 | 8 | 25 | ../../lib/anonymous/server.c | |
_gsasl_support_p | 4 | 7 | 11 | ../../lib/src/supportp.c | |
scram_print_server_final | 4 | 7 | 16 | ../../lib/scram/printer.c | |
scram_print_client_final | 4 | 7 | 16 | ../../lib/scram/printer.c | |
scram_print_server_first | 4 | 7 | 17 | ../../lib/scram/printer.c | |
scram_valid_server_final | 4 | 5 | 13 | ../../lib/scram/validate.c | |
_gsasl_gs2_server_start | 4 | 26 | 44 | ../../lib/gs2/server.c | |
_gsasl_digest_md5_server_start | 4 | 20 | 33 | ../../lib/digest-md5/server.c | |
_gsasl_digest_md5_client_start | 4 | 18 | 30 | ../../lib/digest-md5/client.c | |
gsasl_init | 4 | 11 | 21 | ../../lib/src/init.c | |
cram_md5_digest | 4 | 10 | 19 | ../../lib/cram-md5/digest.c | |
_gsasl_digest_md5_server_decode | 4 | 10 | 23 | ../../lib/digest-md5/server.c | |
_gsasl_digest_md5_server_encode | 4 | 10 | 23 | ../../lib/digest-md5/server.c | |
_gsasl_external_server_step | 4 | 10 | 28 | ../../lib/external/server.c | |
_gsasl_digest_md5_client_decode | 4 | 10 | 23 | ../../lib/digest-md5/client.c | |
_gsasl_digest_md5_client_encode | 4 | 10 | 23 | ../../lib/digest-md5/client.c | |
_gsasl_external_client_step | 3 | 9 | 19 | ../../lib/external/client.c | |
_gsasl_anonymous_client_step | 3 | 9 | 19 | ../../lib/anonymous/client.c | |
digest_md5_parse_finish | 3 | 8 | 16 | ../../lib/digest-md5/parser.c | |
digest_md5_parse_response | 3 | 8 | 16 | ../../lib/digest-md5/parser.c | |
digest_md5_parse_challenge | 3 | 8 | 16 | ../../lib/digest-md5/parser.c | |
main | 3 | 8 | 14 | ../../lib/tests/test-error.c | |
_gsasl_code | 3 | 8 | 20 | ../../lib/src/xcode.c | |
gsasl_property_get | 3 | 7 | 18 | ../../lib/src/property.c | |
hex_p | 3 | 7 | 11 | ../../lib/scram/client.c | |
gsasl_base64_from | 3 | 6 | 13 | ../../lib/src/base64.c | |
gsasl_base64_to | 3 | 6 | 13 | ../../lib/src/base64.c | |
digest_md5_print_finish | 3 | 6 | 15 | ../../lib/digest-md5/printer.c | |
digest_md5_validate_finish | 3 | 5 | 12 | ../../lib/digest-md5/validate.c | |
gsasl_check_version | 3 | 3 | 8 | ../../lib/src/version.c | |
gsasl_mechanism_name | 3 | 3 | 7 | ../../lib/src/mechname.c | |
gsasl_strerror_name | 3 | 3 | 8 | ../../lib/src/error.c | |
_gsasl_gs2_client_start | 3 | 24 | 39 | ../../lib/gs2/client.c | |
cram_md5_challenge | 3 | 14 | 23 | ../../lib/cram-md5/challenge.c | |
start | 3 | 11 | 24 | ../../lib/src/xstart.c | |
_gsasl_digest_md5_set_hashed_secret | 3 | 11 | 22 | ../../lib/digest-md5/server.c | |
_gsasl_cram_md5_server_start | 3 | 10 | 18 | ../../lib/cram-md5/server.c | |
gs2_get_oid | 3 | 10 | 18 | ../../lib/gs2/gs2helper.c | |
map | 3 | 49 | 108 | ../../lib/src/property.c | |
digest_md5_free_challenge | 2 | 8 | 12 | ../../lib/digest-md5/free.c | |
_gsasl_ntlm_client_start | 2 | 7 | 15 | ../../lib/ntlm/ntlm.c | |
_gsasl_login_client_start | 2 | 7 | 15 | ../../lib/login/client.c | |
_gsasl_securid_client_start | 2 | 7 | 15 | ../../lib/securid/client.c | |
_gsasl_digest_md5_server_finish | 2 | 7 | 14 | ../../lib/digest-md5/server.c | |
_gsasl_digest_md5_client_finish | 2 | 7 | 14 | ../../lib/digest-md5/client.c | |
_gsasl_saml20_client_start | 2 | 6 | 13 | ../../lib/saml20/client.c | |
_gsasl_openid20_client_start | 2 | 6 | 13 | ../../lib/openid20/client.c | |
_gsasl_login_server_start | 2 | 6 | 13 | ../../lib/login/server.c | |
_gsasl_openid20_server_start | 2 | 6 | 13 | ../../lib/openid20/server.c | |
_gsasl_saml20_server_start | 2 | 6 | 13 | ../../lib/saml20/server.c | |
_gsasl_login_server_finish | 2 | 6 | 12 | ../../lib/login/server.c | |
gsasl_decode | 2 | 5 | 14 | ../../lib/src/xcode.c | |
gsasl_encode | 2 | 5 | 14 | ../../lib/src/xcode.c | |
gsasl_step | 2 | 5 | 14 | ../../lib/src/xstep.c | |
gsasl_hmac_md5 | 2 | 4 | 9 | ../../lib/src/crypto.c | |
gsasl_md5 | 2 | 4 | 8 | ../../lib/src/crypto.c | |
gsasl_property_fast | 2 | 4 | 10 | ../../lib/src/property.c | |
_gsasl_openid20_server_finish | 2 | 4 | 10 | ../../lib/openid20/server.c | |
_gsasl_openid20_client_finish | 2 | 4 | 10 | ../../lib/openid20/client.c | |
sha1_hex_to_byte | 2 | 4 | 10 | ../../lib/scram/client.c | |
gsasl_hmac_sha1 | 2 | 4 | 9 | ../../lib/src/crypto.c | |
_gsasl_saml20_server_finish | 2 | 4 | 10 | ../../lib/saml20/server.c | |
_gsasl_saml20_client_finish | 2 | 4 | 10 | ../../lib/saml20/client.c | |
gsasl_sha1 | 2 | 4 | 8 | ../../lib/src/crypto.c | |
_gsasl_login_client_finish | 2 | 4 | 10 | ../../lib/login/client.c | |
gsasl_property_set | 2 | 2 | 6 | ../../lib/src/property.c | |
_gsasl_scram_sha1_server_finish | 2 | 18 | 25 | ../../lib/scram/server.c | |
_gsasl_scram_sha1_client_finish | 2 | 12 | 19 | ../../lib/scram/client.c | |
_gsasl_gssapi_client_start | 2 | 10 | 18 | ../../lib/gssapi/client.c | |
digest_md5_free_response | 1 | 7 | 12 | ../../lib/digest-md5/free.c | |
scram_free_client_first | 1 | 5 | 10 | ../../lib/scram/tokens.c | |
scram_free_client_final | 1 | 4 | 9 | ../../lib/scram/tokens.c | |
scram_free_server_first | 1 | 3 | 8 | ../../lib/scram/tokens.c | |
digest_md5_qops2qopstr | 1 | 2 | 16 | ../../lib/digest-md5/qop.c | |
scram_free_server_final | 1 | 2 | 7 | ../../lib/scram/tokens.c | |
_gsasl_ntlm_client_finish | 1 | 2 | 7 | ../../lib/ntlm/ntlm.c | |
_gsasl_securid_client_finish | 1 | 2 | 7 | ../../lib/securid/client.c | |
_gsasl_cram_md5_server_finish | 1 | 2 | 7 | ../../lib/cram-md5/server.c | |
gsasl_server_mechlist | 1 | 1 | 6 | ../../lib/src/listmech.c | |
gsasl_client_mechlist | 1 | 1 | 6 | ../../lib/src/listmech.c | |
gsasl_server_support_p | 1 | 1 | 5 | ../../lib/src/supportp.c | |
digest_md5_free_finish | 1 | 1 | 5 | ../../lib/digest-md5/free.c | |
gsasl_random | 1 | 1 | 5 | ../../lib/src/crypto.c | |
gsasl_client_support_p | 1 | 1 | 5 | ../../lib/src/supportp.c | |
gsasl_callback_set | 1 | 1 | 5 | ../../lib/src/callback.c | |
gsasl_free | 1 | 1 | 5 | ../../lib/src/free.c | |
gsasl_nonce | 1 | 1 | 5 | ../../lib/src/crypto.c | |
to_uchar | 1 | 1 | 5 | ../../lib/digest-md5/nonascii.c | |
gsasl_session_hook_get | 1 | 1 | 5 | ../../lib/src/callback.c | |
gsasl_session_hook_set | 1 | 1 | 5 | ../../lib/src/callback.c | |
hex_to_char | 1 | 1 | 6 | ../../lib/scram/client.c | |
gsasl_server_start | 1 | 1 | 5 | ../../lib/src/xstart.c | |
_gsasl_scram_sha1_plus_server_start | 1 | 1 | 5 | ../../lib/scram/server.c | |
gsasl_callback_hook_get | 1 | 1 | 5 | ../../lib/src/callback.c | |
_gsasl_scram_sha1_server_start | 1 | 1 | 5 | ../../lib/scram/server.c | |
_gsasl_scram_sha1_plus_client_start | 1 | 1 | 5 | ../../lib/scram/client.c | |
gsasl_client_start | 1 | 1 | 5 | ../../lib/src/xstart.c | |
_gsasl_scram_sha1_client_start | 1 | 1 | 5 | ../../lib/scram/client.c | |
_gsasl_digest_md5_hex_to_char | 1 | 1 | 6 | ../../lib/digest-md5/server.c | |
gsasl_callback_hook_set | 1 | 1 | 5 | ../../lib/src/callback.c |