Report generated at: Fri Oct 22 01:46:24 CEST 2010
Total number of functions | 170 |
Number of low risk functions | 140 |
Number of moderate risk functions | 16 |
Number of high risk functions | 14 |
Number of untestable functions | 0 |
Used ranges:
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 |
Cyclomatic
Complexity |
Number of
Statements |
Number of
Lines |
Source File | |
↓ | _gsasl_scram_sha1_server_step | 44 | 153 | 292 | ../../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; /* We don't support channel bindings. */ if (state->cf.cbflag != 'n' && 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. */ { size_t len; char *cbind; rc = gsasl_base64_from (state->cl.cbind, strlen (state->cl.cbind), &cbind, &len); if (rc != 0) return rc; if (len != strlen (state->gs2header)) return GSASL_AUTHENTICATION_ERROR; if (memcmp (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, strlen (state->sf_str), state->sf_str, 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; } |
|||||
↓ | 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 | 48 | 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. < |
|||||
↓ | _gsasl_scram_sha1_client_step | 39 | 140 | 260 | ../../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; /* We don't support channel bindings. */ state->cf.cbflag = 'n'; p = gsasl_property_get (sctx, GSASL_AUTHID); if (!p) return GSASL_NO_AUTHID; /* FIXME check that final document uses query strings. */ 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); /* Save "cbind" and "bare" for next step. */ p = strchr (*output, ','); if (!p) return GSASL_AUTHENTICATION_ERROR; p++; p = strchr (p, ','); if (!p) return GSASL_AUTHENTICATION_ERROR; p++; rc = gsasl_base64_to (*output, p - *output, &state->cl.cbind, NULL); if (rc != 0) return rc; state->cfmb = strdup (p); if (!state->cfmb) return GSASL_MALLOC_ERROR; /* 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, "%d", 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, input_len, input, 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; } |
|||||
↓ | 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; } |
|||||
↓ | scram_parse_client_first | 34 | 80 | 122 | ../../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')) /* FIXME support channel bindings */ return -1; cf->cbflag = *str; str++, len--; 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_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 | 43 | 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 | 29 | 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 | 27 | 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 | 24 | 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 | 19 | 73 | 146 | ../../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; *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_COMPLETE) state->step++; res = GSASL_NEEDS_MORE; break; 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_gs2_server_step | 18 | 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 | 18 | 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; } |
|||||
↓ | _gsasl_securid_server_step | 15 | 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 | 15 | 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; } |
|||||
↓ | register_builtin_mechs | 13 | 38 | 79 | ../../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; #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_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_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 | 26 | 50 | ../../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); if (len <= 0 || gs2cbflag == NULL) { free (gs2cbflag); return GSASL_MALLOC_ERROR; } *gs2hlen = len; } |
|||||
↓ | 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; } |
|||||
↓ | scram_valid_client_first | 13 | 13 | 37 | ../../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; /* FIXME check that cbname matches [A-Za-z0-9.-]. */ /* 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; } |
|||||
↓ | scram_print_client_first | 11 | 22 | 42 | ../../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_ntlm_client_step | 11 | 53 | 105 | ../../lib/ntlm/ntlm.c | |
gs2_get_cred | 10 | 35 | 60 | ../../lib/gs2/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_saml20_server_step | 9 | 34 | 69 | ../../lib/saml20/server.c | |
_gsasl_cram_md5_server_step | 8 | 34 | 62 | ../../lib/cram-md5/server.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 | |
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 | 27 | 41 | ../../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 | |
_gsasl_saml20_client_step | 7 | 23 | 55 | ../../lib/saml20/client.c | |
digest_md5_validate_challenge | 6 | 7 | 18 | ../../lib/digest-md5/validate.c | |
_gsasl_plain_client_step | 6 | 26 | 47 | ../../lib/plain/client.c | |
_gsasl_scram_sha1_server_start | 6 | 24 | 39 | ../../lib/scram/server.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 | 7 | 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 | 5 | 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 | 17 | ../../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_scram_sha1_client_start | 4 | 16 | 30 | ../../lib/scram/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 | |
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 | |
digest_md5_parse_finish | 3 | 11 | 20 | ../../lib/digest-md5/parser.c | |
digest_md5_parse_response | 3 | 11 | 20 | ../../lib/digest-md5/parser.c | |
digest_md5_parse_challenge | 3 | 11 | 20 | ../../lib/digest-md5/parser.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 | 21 | 43 | 96 | ../../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_login_server_start | 2 | 6 | 13 | ../../lib/login/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_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 | |
sha1_hex_to_byte | 2 | 4 | 10 | ../../lib/scram/client.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 | 15 | 22 | ../../lib/scram/server.c | |
_gsasl_scram_sha1_client_finish | 2 | 11 | 18 | ../../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 | |
gsasl_server_start | 1 | 1 | 5 | ../../lib/src/xstart.c | |
gsasl_callback_hook_get | 1 | 1 | 5 | ../../lib/src/callback.c | |
gsasl_client_start | 1 | 1 | 5 | ../../lib/src/xstart.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 |