static void mech_external_auth_continue(struct auth_request *request, const unsigned char *data, size_t data_size) { const char *authzid, *error; authzid = t_strndup(data, data_size); if (request->user == NULL) { auth_request_log_info(request, AUTH_SUBSYS_MECH, "username not known"); auth_request_fail(request); return; } /* this call is done simply to put the username through translation settings */ if (!auth_request_set_username(request, "", &error)) { auth_request_log_info(request, AUTH_SUBSYS_MECH, "Invalid username"); auth_request_fail(request); return; } if (*authzid != '\0' && !auth_request_set_login_username(request, authzid, &error)) { /* invalid login username */ auth_request_log_info(request, AUTH_SUBSYS_MECH, "login user: %s", error); auth_request_fail(request); } else { auth_request_verify_plain(request, "", plain_verify_callback); } }
static void mech_digest_md5_auth_continue(struct auth_request *auth_request, const unsigned char *data, size_t data_size) { struct digest_auth_request *request = (struct digest_auth_request *)auth_request; const char *username, *error; if (parse_digest_response(request, data, data_size, &error)) { if (auth_request->realm != NULL && strchr(request->username, '@') == NULL) { username = t_strconcat(request->username, "@", auth_request->realm, NULL); auth_request->domain_is_realm = TRUE; } else { username = request->username; } if (auth_request_set_username(auth_request, username, &error) && (request->authzid == NULL || auth_request_set_login_username(auth_request, request->authzid, &error))) { auth_request_lookup_credentials(auth_request, "DIGEST-MD5", credentials_callback); return; } } if (error != NULL) auth_request_log_info(auth_request, AUTH_SUBSYS_MECH, "%s", error); auth_request_fail(auth_request); }
static void mech_plain_auth_continue(struct auth_request *request, const unsigned char *data, size_t data_size) { const char *authid, *authenid, *error; char *pass; size_t i, len; int count; /* authorization ID \0 authentication ID \0 pass. */ authid = (const char *) data; authenid = NULL; pass = NULL; count = 0; for (i = 0; i < data_size; i++) { if (data[i] == '\0') { if (++count == 1) authenid = (const char *) data + i+1; else { i++; len = data_size - i; pass = p_strndup(unsafe_data_stack_pool, data+i, len); break; } } } if (authenid != NULL && strcmp(authid, authenid) == 0) { /* the login username isn't different */ authid = ""; } if (count != 2) { /* invalid input */ auth_request_log_info(request, AUTH_SUBSYS_MECH, "invalid input"); auth_request_fail(request); } else if (!auth_request_set_username(request, authenid, &error)) { /* invalid username */ auth_request_log_info(request, AUTH_SUBSYS_MECH, "%s", error); auth_request_fail(request); } else if (*authid != '\0' && !auth_request_set_login_username(request, authid, &error)) { /* invalid login username */ auth_request_log_info(request, AUTH_SUBSYS_MECH, "login user: %s", error); auth_request_fail(request); } else { auth_request_verify_plain(request, pass, plain_verify_callback); } /* make sure it's cleared */ if (pass != NULL) safe_memset(pass, 0, strlen(pass)); }
static void mech_dovecot_token_auth_continue(struct auth_request *request, const unsigned char *data, size_t data_size) { const char *session_id, *username, *pid, *service, *error; char *auth_token; size_t i, len; int count; /* service \0 pid \0 username \0 session_id \0 auth_token */ service = (const char *) data; session_id = username = pid = auth_token = NULL; count = 0; for (i = 0; i < data_size; i++) { if (data[i] == '\0') { count++; i++; if (count == 1) pid = (const char *)data + i; else if (count == 2) username = (const char *)data + i; else if (count == 3) session_id = (const char *)data + i; else { len = data_size - i; auth_token = p_strndup(unsafe_data_stack_pool, data+i, len); break; } } } if (count != 4) { /* invalid input */ auth_request_log_info(request, AUTH_SUBSYS_MECH, "invalid input"); auth_request_fail(request); } else if (!auth_request_set_username(request, username, &error)) { /* invalid username */ auth_request_log_info(request, AUTH_SUBSYS_MECH, "%s", error); auth_request_fail(request); } else { const char *valid_token = auth_token_get(service, pid, request->user, session_id); if (auth_token != NULL && strcmp(auth_token, valid_token) == 0) { request->passdb_success = TRUE; auth_request_success(request, NULL, 0); } else { auth_request_fail(request); } } /* make sure it's cleared */ if (auth_token != NULL) safe_memset(auth_token, 0, strlen(auth_token)); }
static int master_input_auth_request(struct auth_master_connection *conn, const char *args, const char *cmd, struct auth_request **request_r, const char **error_r) { struct auth_request *auth_request; const char *const *list, *name, *arg, *username; unsigned int id; /* <id> <userid> [<parameters>] */ list = t_strsplit_tab(args); if (list[0] == NULL || list[1] == NULL || str_to_uint(list[0], &id) < 0) { i_error("BUG: Master sent broken %s", cmd); return -1; } auth_request = auth_request_new_dummy(); auth_request->id = id; auth_request->master = conn; auth_master_connection_ref(conn); username = list[1]; for (list += 2; *list != NULL; list++) { arg = strchr(*list, '='); if (arg == NULL) { name = *list; arg = ""; } else { name = t_strdup_until(*list, arg); arg++; } (void)auth_request_import_info(auth_request, name, arg); } if (auth_request->service == NULL) { i_error("BUG: Master sent %s request without service", cmd); auth_request_unref(&auth_request); auth_master_connection_unref(&conn); return -1; } auth_request_init(auth_request); if (!auth_request_set_username(auth_request, username, error_r)) { *request_r = auth_request; return 0; } *request_r = auth_request; return 1; }
static int postfix_input_auth_request(struct auth_postfix_connection *conn, const char *username, struct auth_request **request_r, const char **error_r) { struct auth_request *auth_request; auth_request = auth_request_new_dummy(); auth_request->id = 1; auth_request->context = conn; auth_postfix_connection_ref(conn); if (!auth_request_set_username(auth_request, username, error_r)) { *request_r = auth_request; return FALSE; } (void)auth_request_import_info(auth_request, "service", "postfix"); auth_request_init(auth_request); *request_r = auth_request; return TRUE; }
static void mech_cram_md5_auth_continue(struct auth_request *auth_request, const unsigned char *data, size_t data_size) { struct cram_auth_request *request = (struct cram_auth_request *)auth_request; const char *error; if (parse_cram_response(request, data, data_size, &error)) { if (auth_request_set_username(auth_request, request->username, &error)) { auth_request_lookup_credentials(auth_request, "CRAM-MD5", credentials_callback); return; } } if (error == NULL) error = "authentication failed"; auth_request_log_info(auth_request, AUTH_SUBSYS_MECH, "%s", error); auth_request_fail(auth_request); }
static void mech_apop_auth_initial(struct auth_request *auth_request, const unsigned char *data, size_t data_size) { struct apop_auth_request *request = (struct apop_auth_request *)auth_request; const unsigned char *tmp, *end, *username = NULL; unsigned long pid, connect_uid, timestamp; const char *error; /* pop3-login handles sending the challenge and getting the response. Our input here is: <challenge> \0 <username> \0 <response> */ if (data_size == 0) { /* Should never happen */ auth_request_log_info(auth_request, "apop", "no initial respone"); auth_request_fail(auth_request); return; } tmp = data; end = data + data_size; /* get the challenge */ while (tmp != end && *tmp != '\0') tmp++; request->challenge = p_strdup_until(request->pool, data, tmp); if (tmp != end) { /* get the username */ username = ++tmp; while (tmp != end && *tmp != '\0') tmp++; } if (tmp + 1 + 16 != end) { /* Should never happen */ auth_request_log_info(auth_request, "apop", "malformed data"); auth_request_fail(auth_request); return; } memcpy(request->response_digest, tmp + 1, sizeof(request->response_digest)); /* the challenge must begin with trusted unique ID. we trust only ourself, so make sure it matches our connection specific UID which we told to client in handshake. Also require a timestamp which is later than this process's start time. */ if (sscanf(request->challenge, "<%lx.%lx.%lx.", &pid, &connect_uid, ×tamp) != 3 || connect_uid != auth_request->connect_uid || pid != (unsigned long)getpid() || (time_t)timestamp < process_start_time) { auth_request_log_info(auth_request, "apop", "invalid challenge"); auth_request_fail(auth_request); return; } if (!auth_request_set_username(auth_request, (const char *)username, &error)) { auth_request_log_info(auth_request, "apop", "%s", error); auth_request_fail(auth_request); return; } auth_request_lookup_credentials(auth_request, "PLAIN", apop_credentials_callback); }