static apr_status_t setUserInDb(apr_dbm_t *userDbm, const char *user, const char *password, yubiauth_dir_cfg *cfg, request_rec *r) { char *timeAuthenticated = NULL; char *dbToken = NULL; //This is used to store pw:date char *userKey = NULL; apr_datum_t key, value; apr_status_t rv; /* Built up some combination of token:time */ timeAuthenticated = apr_psprintf(r->pool, "%" APR_TIME_T_FMT, (apr_time_t) (apr_time_sec(apr_time_now()))); dbToken = apr_pstrcat(r->pool, password, ":", timeAuthenticated, NULL); /* store OTP:time combo with username as key in DB */ userKey = getDbKey(user, cfg, r); key = string2datum(userKey, r); value = string2datum(dbToken, r); /* Pump user into db, store un, cookie value, creation date, * let this expire sometime */ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_DEBUG, 0, r, LOG_PREFIX "Writing key: %s and value: %s to db", key.dptr, value.dptr); rv = apr_dbm_store(userDbm, key, value); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, LOG_PREFIX "Error writing to db ... with key: %s and value: %s", key.dptr, value.dptr); } /* Spit back, so we can decide wheather s.th. went wrong or not */ return rv; }
/* User Key because the username is the key to the db */ static void deleteKeyFromDb(apr_dbm_t *userDbm, const char *userKey, request_rec *r) { apr_datum_t key; apr_status_t rv; key = string2datum(userKey, r); ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_DEBUG, 0, r, LOG_PREFIX "Deleting key %s", key.dptr); rv = apr_dbm_delete(userDbm, key); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, LOG_PREFIX "Could not delete key %s", key.dptr); } }
static authn_status authn_check_otp(request_rec *r, const char *user, const char *password) { apr_status_t rv; apr_dbm_t *userDbm = NULL; yubiauth_dir_cfg *cfg = ap_get_module_config(r->per_dir_config, &authn_yubikey_module); apr_datum_t key,dbUserRecord; key.dptr = NULL; dbUserRecord.dptr = NULL; char *lookedUpToken = NULL; char *lookedUpPassword = NULL; //This is the OTP token char *dbUserKey = (char *) malloc(sizeof(user)); apr_size_t passwordLength = 0; apr_time_t lookedUpDate = 0; /* No username and no password is set */ if (!*user || !*password) return AUTH_DENIED; /* Since the password field contains possibly a password and the OTP token, we * have to break that up here */ passwordLength = (apr_size_t) strlen(password) - YUBIKEY_TOKEN_LENGTH; ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_DEBUG, 0, r, LOG_PREFIX "Username is: %s and password is: %s", user, &password[passwordLength]); /* Now open the User DB and see if the user really is one of us. * for that we save the 12char token:username combo. * Ideally we can fill that with the htpasswd utility * NOTE: enter full password here */ if (!isUserValid(user, password, cfg, r)) { return AUTH_DENIED; } openDb(&userDbm, cfg->tmpAuthDbFilename, r); dbUserKey = strcpy(dbUserKey, user); dbUserKey = getDbKey(dbUserKey, cfg, r); key = string2datum(dbUserKey, r); ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_DEBUG, 0, r, LOG_PREFIX "Fetching token (pw:time) for user %s from db ...", user); rv = apr_dbm_fetch(userDbm, key, &dbUserRecord); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, LOG_PREFIX "unable to fetch the user (%s) from the" "Database, better abort here.", user); closeDb(userDbm, r); return HTTP_INTERNAL_SERVER_ERROR; } if (dbUserRecord.dptr != NULL) { /* it's separated pw:time here */ const char *sep = ":"; char *time; lookedUpToken = apr_pstrmemdup(r->pool, dbUserRecord.dptr, dbUserRecord.dsize); /* Break down the token into it's pw:time components */ lookedUpPassword = apr_strtok(lookedUpToken, sep, &time); lookedUpDate = (apr_time_t) apr_atoi64(time); ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_DEBUG, 0, r, LOG_PREFIX "We could extrace these values from the token:"); ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_DEBUG, 0, r, LOG_PREFIX "The looked up token for the user: %s", user); ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_DEBUG, 0, r, LOG_PREFIX "The looked up password: %s", lookedUpPassword); ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_DEBUG, 0, r, LOG_PREFIX "The looked up time: %" APR_TIME_T_FMT, lookedUpDate); ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_DEBUG, 0, r, LOG_PREFIX "The looked up token: %s", lookedUpToken); } ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_DEBUG, 0, r, LOG_PREFIX "Fetched token (%s) ...", lookedUpToken); /* password has to be set, if the pw content is NULL or empty, we have * catched that earlier ... */ if (lookedUpPassword != NULL && !strcmp(lookedUpPassword, &password[passwordLength])) { /* The date expired */ if (passwordExpired(user, lookedUpDate, cfg->timeoutSeconds, r)) { /* Delete user record */ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_DEBUG, 0, r, LOG_PREFIX "Remove expired entry for user : %s", user); deleteKeyFromDb(userDbm, user, cfg, r); closeDb(userDbm, r); return AUTH_DENIED; } else { closeDb(userDbm, r); return AUTH_GRANTED; } } else { int authenticationSuccessful = 0; int ret = YUBIKEY_CLIENT_BAD_OTP; /* We could not lookup the password, verify the sent password */ ret = yubikey_client_simple_request(&password[passwordLength], 1, 0, NULL, r); if (ret == YUBIKEY_CLIENT_OK) { authenticationSuccessful = 1; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, LOG_PREFIX "Authentication failed, reason: %s", yubikey_client_strerror(ret)); return AUTH_DENIED; } /* We could successfully authenticate the user */ if (authenticationSuccessful) { /* Try to write the user into the db */ if (setUserInDb(userDbm, user, &password[passwordLength], cfg, r) != APR_SUCCESS) { /* Abort, we could not write the user into the db after * authenticating him ... */ closeDb(userDbm, r); return HTTP_INTERNAL_SERVER_ERROR; } /* User could be written to the db*/ closeDb(userDbm, r); return AUTH_GRANTED; } /* Could not authenticate successful */ closeDb(userDbm, r); return AUTH_DENIED; } /* Something went wrong or we did not think about it, better deny */ closeDb(userDbm, r); return AUTH_DENIED; }