00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #define APR_WANT_STRFUNC
00027 #include "apr_want.h"
00028 #include "apr_strings.h"
00029 #include "apr_dbm.h"
00030 #include "apr_md5.h"
00031
00032 #include "ap_provider.h"
00033 #include "httpd.h"
00034 #include "http_config.h"
00035 #include "http_core.h"
00036 #include "http_log.h"
00037 #include "http_protocol.h"
00038 #include "http_request.h"
00039
00040 #include "mod_auth.h"
00041
00042 typedef struct {
00043 char *pwfile;
00044 char *dbmtype;
00045 } authn_dbm_config_rec;
00046
00047 static void *create_authn_dbm_dir_config(apr_pool_t *p, char *d)
00048 {
00049 authn_dbm_config_rec *conf = apr_palloc(p, sizeof(*conf));
00050
00051 conf->pwfile = NULL;
00052 conf->dbmtype = "default";
00053
00054 return conf;
00055 }
00056
00057 static const char *set_dbm_type(cmd_parms *cmd,
00058 void *dir_config,
00059 const char *arg)
00060 {
00061 authn_dbm_config_rec *conf = dir_config;
00062
00063 conf->dbmtype = apr_pstrdup(cmd->pool, arg);
00064 return NULL;
00065 }
00066
00067 static const command_rec authn_dbm_cmds[] =
00068 {
00069 AP_INIT_TAKE1("AuthDBMUserFile", ap_set_file_slot,
00070 (void *)APR_OFFSETOF(authn_dbm_config_rec, pwfile),
00071 OR_AUTHCFG, "dbm database file containing user IDs and passwords"),
00072 AP_INIT_TAKE1("AuthDBMType", set_dbm_type,
00073 NULL,
00074 OR_AUTHCFG, "what type of DBM file the user file is"),
00075 {NULL}
00076 };
00077
00078 module AP_MODULE_DECLARE_DATA authn_dbm_module;
00079
00080 static apr_status_t fetch_dbm_value(const char *dbmtype, const char *dbmfile,
00081 const char *user, char **value,
00082 apr_pool_t *pool)
00083 {
00084 apr_dbm_t *f;
00085 apr_datum_t key, val;
00086 apr_status_t rv;
00087
00088 rv = apr_dbm_open_ex(&f, dbmtype, dbmfile, APR_DBM_READONLY,
00089 APR_OS_DEFAULT, pool);
00090
00091 if (rv != APR_SUCCESS) {
00092 return rv;
00093 }
00094
00095 key.dptr = (char*)user;
00096 #ifndef NETSCAPE_DBM_COMPAT
00097 key.dsize = strlen(key.dptr);
00098 #else
00099 key.dsize = strlen(key.dptr) + 1;
00100 #endif
00101
00102 *value = NULL;
00103
00104 if (apr_dbm_fetch(f, key, &val) == APR_SUCCESS && val.dptr) {
00105 *value = apr_pstrmemdup(pool, val.dptr, val.dsize);
00106 }
00107
00108 apr_dbm_close(f);
00109
00110 return rv;
00111 }
00112
00113 static authn_status check_dbm_pw(request_rec *r, const char *user,
00114 const char *password)
00115 {
00116 authn_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config,
00117 &authn_dbm_module);
00118 apr_status_t rv;
00119 char *dbm_password;
00120 char *colon_pw;
00121
00122 rv = fetch_dbm_value(conf->dbmtype, conf->pwfile, user, &dbm_password,
00123 r->pool);
00124
00125 if (rv != APR_SUCCESS) {
00126 ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
00127 "could not open dbm (type %s) auth file: %s",
00128 conf->dbmtype, conf->pwfile);
00129 return AUTH_GENERAL_ERROR;
00130 }
00131
00132 if (!dbm_password) {
00133 return AUTH_USER_NOT_FOUND;
00134 }
00135
00136 colon_pw = ap_strchr(dbm_password, ':');
00137 if (colon_pw) {
00138 *colon_pw = '\0';
00139 }
00140
00141 rv = apr_password_validate(password, dbm_password);
00142
00143 if (rv != APR_SUCCESS) {
00144 return AUTH_DENIED;
00145 }
00146
00147 return AUTH_GRANTED;
00148 }
00149
00150 static authn_status get_dbm_realm_hash(request_rec *r, const char *user,
00151 const char *realm, char **rethash)
00152 {
00153 authn_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config,
00154 &authn_dbm_module);
00155 apr_status_t rv;
00156 char *dbm_hash;
00157 char *colon_hash;
00158
00159 rv = fetch_dbm_value(conf->dbmtype, conf->pwfile,
00160 apr_pstrcat(r->pool, user, ":", realm, NULL),
00161 &dbm_hash, r->pool);
00162
00163 if (rv != APR_SUCCESS) {
00164 ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
00165 "Could not open dbm (type %s) hash file: %s",
00166 conf->dbmtype, conf->pwfile);
00167 return AUTH_GENERAL_ERROR;
00168 }
00169
00170 if (!dbm_hash) {
00171 return AUTH_USER_NOT_FOUND;
00172 }
00173
00174 colon_hash = ap_strchr(dbm_hash, ':');
00175 if (colon_hash) {
00176 *colon_hash = '\0';
00177 }
00178
00179 *rethash = dbm_hash;
00180
00181 return AUTH_USER_FOUND;
00182 }
00183
00184 static const authn_provider authn_dbm_provider =
00185 {
00186 &check_dbm_pw,
00187 &get_dbm_realm_hash
00188 };
00189
00190 static void register_hooks(apr_pool_t *p)
00191 {
00192 ap_register_provider(p, AUTHN_PROVIDER_GROUP, "dbm", "0",
00193 &authn_dbm_provider);
00194 }
00195
00196 module AP_MODULE_DECLARE_DATA authn_dbm_module =
00197 {
00198 STANDARD20_MODULE_STUFF,
00199 create_authn_dbm_dir_config,
00200 NULL,
00201 NULL,
00202 NULL,
00203 authn_dbm_cmds,
00204 register_hooks
00205 };