"Fossies" - the Fresh Open Source Software Archive

Member "mod_auth_ldap/mod_auth_ldap.c" (15 Apr 2000, 12681 Bytes) of package /linux/www/apache_httpd_modules/old/mod_auth_ldap-0.5.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1  /*
    2   * mod_auth_ldap
    3   *
    4   * User Authentication against LDAP database
    5   *
    6   * Alexander Mayrhofer axelm+ldap@nona.net
    7   *
    8   * http://nona.net/software/ldap/
    9   *
   10   */
   11 
   12  /* 
   13   * MODULE-DEFINITION-START
   14   * Name: ldap_auth_module
   15   * ConfigStart
   16     LDAP_LIBS="-lldap -llber"
   17     LIBS="$LIBS $LDAP_LIBS"
   18     echo "       + using LDAP libraries for auth_ldap module"
   19   * ConfigEnd
   20   * MODULE-DEFINITION-END
   21   */
   22 
   23 #include "httpd.h"
   24 #include "http_config.h"
   25 #include "http_core.h"
   26 #include "http_log.h"
   27 #include "http_protocol.h"
   28 #include <lber.h>
   29 #include <ldap.h>
   30 #include <unistd.h>
   31 
   32 #define SHA1_DIGEST_LENGTH 29 /* sha1 digest length including null character */
   33 
   34 typedef struct  {
   35 
   36     char *auth_ldaphosts;
   37     char *auth_ldapbinddn;
   38     char *auth_ldapbindpassword;
   39     char *auth_ldapbasedn;
   40     char *auth_ldapuserkey;
   41     char *auth_ldappasskey;
   42     char *auth_ldapgroupkey;
   43     char *auth_ldapsearchscope;
   44     int   auth_ldapauthoritative;
   45     int   auth_ldapbasesearch;
   46     int   auth_ldapcryptpasswords;
   47     int   auth_ldapbindasuser;
   48     int   auth_ldapschemeprefix;
   49 
   50 } ldap_auth_config_rec;
   51 
   52 void *create_ldap_auth_dir_config (pool *p, char *d)
   53 {
   54     ldap_auth_config_rec *sec
   55        = (ldap_auth_config_rec *)ap_pcalloc (p, sizeof(ldap_auth_config_rec));
   56 
   57     sec->auth_ldaphosts = NULL;
   58     sec->auth_ldapbinddn = NULL;
   59     sec->auth_ldapbindpassword = NULL;
   60     sec->auth_ldapbasedn = NULL;
   61     sec->auth_ldapsearchscope = NULL;
   62     sec->auth_ldapauthoritative = 1; /* fortress is secure by default */
   63     sec->auth_ldapbasesearch = 0; 
   64     sec->auth_ldapcryptpasswords = 0; 
   65     sec->auth_ldapbindasuser = 0; /* by default, we bind as configured user to ldap */
   66     sec->auth_ldapschemeprefix = 0; /* no scheme prefix in password strings */
   67 
   68     return sec;
   69 }
   70 
   71 command_rec ldap_auth_cmds[] = {
   72 { "AuthLDAPHosts", ap_set_string_slot,
   73     (void*)XtOffsetOf(ldap_auth_config_rec, auth_ldaphosts),
   74     OR_AUTHCFG, TAKE1, 
   75     "List of LDAP hosts which should be queried" },
   76 { "AuthLDAPBindDN", ap_set_string_slot,
   77     (void*)XtOffsetOf(ldap_auth_config_rec, auth_ldapbinddn),
   78     OR_AUTHCFG, TAKE1, 
   79     "As which DN to bind to the LDAP directory" },
   80 { "AuthLDAPBindPassword", ap_set_string_slot,
   81     (void*)XtOffsetOf(ldap_auth_config_rec, auth_ldapbindpassword),
   82     OR_AUTHCFG, TAKE1, 
   83     "The password corresponding to AuthLDAPBindDN" },
   84 { "AuthLDAPBaseDN", ap_set_string_slot,
   85     (void*)XtOffsetOf(ldap_auth_config_rec, auth_ldapbasedn),
   86     OR_AUTHCFG, TAKE1, 
   87     "The DN in the LDAP directory which contains the per-user subnodes" },
   88 { "AuthLDAPUserKey", ap_set_string_slot,
   89     (void*)XtOffsetOf(ldap_auth_config_rec, auth_ldapuserkey),
   90     OR_AUTHCFG, TAKE1, 
   91     "The key which's value contains the username in the directory" },
   92 { "AuthLDAPPassKey", ap_set_string_slot,
   93     (void*)XtOffsetOf(ldap_auth_config_rec, auth_ldappasskey),
   94     OR_AUTHCFG, TAKE1, 
   95     "The key to the user's password" },
   96 { "AuthLDAPGroupKey", ap_set_string_slot,
   97     (void*)XtOffsetOf(ldap_auth_config_rec, auth_ldapgroupkey),
   98     OR_AUTHCFG, TAKE1, 
   99     "the key to the user's group membership string" },
  100 { "AuthLDAPBaseSearch", ap_set_flag_slot,
  101     (void*)XtOffsetOf(ldap_auth_config_rec, auth_ldapbasesearch),
  102     OR_AUTHCFG, FLAG, 
  103     "Deprecated. Use 'AuthLDAPSearchScope'. Anyway: Set to 'on' if you do want to do a base search only" },
  104 { "AuthLDAPSearchScope", ap_set_string_slot,
  105     (void*)XtOffsetOf(ldap_auth_config_rec, auth_ldapsearchscope),
  106     OR_AUTHCFG, TAKE1, 
  107     "Set Scope when searching in LDAP. Can be 'base', 'onelevel' or 'subtree'" },
  108 { "AuthLDAPAuthoritative", ap_set_flag_slot,
  109     (void*)XtOffsetOf(ldap_auth_config_rec, auth_ldapauthoritative),
  110     OR_AUTHCFG, FLAG, 
  111     "Set to 'off' to allow control to be passed on, if UserID unknow to this module" },
  112 { "AuthLDAPCryptPasswords", ap_set_flag_slot,
  113     (void*)XtOffsetOf(ldap_auth_config_rec, auth_ldapcryptpasswords),
  114     OR_AUTHCFG, FLAG, 
  115     "Set to 'on' if you do have crypted password strings" },
  116 { "AuthLDAPBindAsUser", ap_set_flag_slot,
  117     (void*)XtOffsetOf(ldap_auth_config_rec, auth_ldapbindasuser),
  118     OR_AUTHCFG, FLAG, 
  119     "Set to 'on' if you want to bind as the user for authentication" },
  120 { "AuthLDAPSchemePrefix", ap_set_flag_slot,
  121     (void*)XtOffsetOf(ldap_auth_config_rec, auth_ldapschemeprefix),
  122     OR_AUTHCFG, FLAG, 
  123     "Set to 'on' if you have scheme-prefixed password strings as described in rfc2307" },
  124 { NULL }
  125 };
  126 
  127 module ldap_auth_module;
  128 
  129 char *get_ldap_val(request_rec *r, char *user, char *pass, ldap_auth_config_rec *conf, char *attr) {
  130     char *bindas, *bindpass;
  131     LDAP *ldap;
  132     LDAPMessage *ld_result, *ld_entry;
  133     char ldap_query[200];
  134     char ldap_base[200];
  135     char **ld_values;
  136     char *retval = NULL;
  137     int  ldap_scope;
  138 
  139     if(!(ldap = ldap_open(conf->auth_ldaphosts, LDAP_PORT))) { 
  140         printf("ldap host: %s", conf->auth_ldaphosts);
  141         ap_log_reason("ldap_open failed", conf->auth_ldaphosts, r);
  142         return NULL;
  143         }
  144     if(conf->auth_ldapbindasuser) {
  145        if ((!pass) || (!strcmp(pass,""))) {
  146           ap_log_reason("ldap_bind: no password given (BindAsUser enabled)!", NULL, r);
  147           return NULL;
  148           }
  149        ap_snprintf(ldap_base, sizeof ldap_base, "%s=%s,%s", conf->auth_ldapuserkey, user, conf->auth_ldapbasedn);
  150        bindas = ldap_base;
  151        bindpass = pass;
  152        }
  153     else {
  154        bindas = conf->auth_ldapbinddn;
  155        bindpass = conf->auth_ldapbindpassword;
  156        }
  157     if(ldap_simple_bind_s(ldap, bindas, bindpass)) {
  158         ap_log_reason("ldap_bind failed", bindas, r);
  159         return NULL;
  160         }
  161     if(!attr) {
  162     ldap_unbind_s(ldap);
  163     return "bind";
  164     }
  165     ap_snprintf(ldap_query, sizeof ldap_query, "%s=%s", conf->auth_ldapuserkey, user);
  166     /* check for search scope */
  167     if(conf->auth_ldapbasesearch || (conf->auth_ldapsearchscope && 
  168                   !strcasecmp(conf->auth_ldapsearchscope, "base"))) {
  169        ap_snprintf(ldap_base, sizeof ldap_base, "%s=%s,%s", conf->auth_ldapuserkey, user, conf->auth_ldapbasedn);
  170        ldap_scope = LDAP_SCOPE_BASE;
  171        }
  172     else {
  173        ap_snprintf(ldap_base, sizeof ldap_base, "%s", conf->auth_ldapbasedn);
  174        if(conf->auth_ldapsearchscope) {
  175            ldap_scope = strcasecmp(conf->auth_ldapsearchscope, "subtree") ?
  176                         LDAP_SCOPE_ONELEVEL : LDAP_SCOPE_SUBTREE; 
  177            }
  178        }
  179     if(ldap_search_s(ldap, ldap_base, ldap_scope,
  180                      ldap_query, NULL, 0, &ld_result)) {
  181         ap_log_reason("ldap_search failed", ldap_query, r);
  182         ldap_unbind_s(ldap);
  183         return NULL;
  184         }
  185     if(!(ld_entry = ldap_first_entry(ldap, ld_result))) {
  186         ap_log_reason("user not found", user, r);
  187         ldap_unbind_s(ldap);
  188         return NULL;
  189         }
  190     if(!(ld_values = ldap_get_values(ldap, ld_entry, attr))) {
  191         ap_log_reason("ldap_get_values failed", attr, r);
  192         ldap_unbind_s(ldap);
  193         return NULL;
  194         }
  195     
  196     retval = ap_palloc (r->pool, strlen(ld_values[0])+1);
  197     strcpy(retval,ld_values[0]);
  198 
  199     ldap_value_free(ld_values);
  200     ldap_unbind_s(ldap);
  201 
  202     return retval; 
  203 }
  204 
  205 char  *get_ldap_grp(request_rec *r, char *user, char *pass, ldap_auth_config_rec *conf) {
  206     return get_ldap_val(r, user, pass, conf, conf->auth_ldapgroupkey);
  207 }
  208 
  209 int ldap_authenticate_basic_user (request_rec *r)
  210 {
  211     ldap_auth_config_rec *sec =
  212       (ldap_auth_config_rec *)ap_get_module_config (r->per_dir_config,
  213                         &ldap_auth_module);
  214     conn_rec *c = r->connection;
  215     char *sent_pw, *real_pw, *digest;
  216     char errstr[MAX_STRING_LEN];
  217     int res;
  218 
  219     if ((res = ap_get_basic_auth_pw (r, (const char **)&sent_pw)))
  220         return res;
  221 
  222     if(!sec->auth_ldapuserkey)
  223         return DECLINED;
  224     
  225     if(sec->auth_ldapbindasuser) {
  226         if(!(real_pw = get_ldap_val(r, c->user, sent_pw, sec, sec->auth_ldappasskey))) {
  227         if (!(sec->auth_ldapauthoritative))
  228             return DECLINED;
  229             ap_snprintf(errstr, sizeof(errstr), "LDAP user %s not found or password invalid", c->user);
  230         ap_log_reason (errstr, r->filename, r);
  231             ap_note_basic_auth_failure (r);
  232             return AUTH_REQUIRED;
  233             }
  234         return OK;
  235         }
  236     if(!(real_pw = get_ldap_val(r, c->user, sent_pw, sec, sec->auth_ldappasskey))) {
  237     if (!(sec->auth_ldapauthoritative))
  238         return DECLINED;
  239         ap_snprintf(errstr, sizeof(errstr), "LDAP user %s not found", c->user);
  240     ap_log_reason (errstr, r->filename, r);
  241     ap_note_basic_auth_failure (r);
  242     return AUTH_REQUIRED;
  243     }    
  244     if (!sec->auth_ldapbindasuser) { 
  245         /* We didn't use the credentials to bind to LDAP, so check them.. */
  246         if (sec->auth_ldapschemeprefix) {
  247            /* we do use scheme prefixes as described in RFC2307 */
  248            /* currently sha, crypt are supported */
  249            if (!strncasecmp("{crypt}", real_pw, 7)) {
  250               if(!strcmp(real_pw+7, crypt(sent_pw,real_pw+7))) 
  251          return OK;
  252               }
  253            if (!strncasecmp("{sha}", real_pw, 5)) {
  254               digest = ap_palloc (r->pool, SHA1_DIGEST_LENGTH);
  255               sha1_digest(sent_pw, strlen(sent_pw), digest);
  256               if(!strcmp(real_pw+5, digest))
  257          return OK;
  258               }
  259            ap_snprintf(errstr, sizeof(errstr), 
  260             "user %s: password mismatch %s, %s", c->user, real_pw+5, digest);
  261            ap_log_reason (errstr, r->uri, r);
  262            ap_note_basic_auth_failure (r);
  263            return AUTH_REQUIRED;
  264            }
  265 
  266         if (sec->auth_ldapcryptpasswords) {
  267            /* Passwords are crypted */
  268            if(strcmp(real_pw,crypt(sent_pw,real_pw))) {  
  269               ap_snprintf(errstr, sizeof(errstr), 
  270             "user %s: password mismatch",c->user);
  271               ap_log_reason (errstr, r->uri, r);
  272           ap_note_basic_auth_failure (r);
  273           return AUTH_REQUIRED;
  274               }
  275            }
  276         else {
  277            /* We have clear text passwords ... */
  278            if(strcmp(real_pw,sent_pw)) {  
  279                ap_snprintf(errstr, sizeof(errstr), 
  280             "user %s: password mismatch",c->user);
  281            ap_log_reason (errstr, r->uri, r);
  282            ap_note_basic_auth_failure (r);
  283            return AUTH_REQUIRED;
  284                }
  285            }
  286         }
  287     return OK;
  288 }
  289     
  290 /* Checking ID */
  291     
  292 int ldap_check_auth(request_rec *r) {
  293     ldap_auth_config_rec *sec =
  294       (ldap_auth_config_rec *)ap_get_module_config (r->per_dir_config,
  295                         &ldap_auth_module);
  296     char *user = r->connection->user;
  297     int m = r->method_number;
  298     char errstr[MAX_STRING_LEN];
  299     
  300     const array_header *reqs_arr = ap_requires (r);
  301     require_line *reqs = reqs_arr ? (require_line *)reqs_arr->elts : NULL;
  302 
  303     register int x;
  304     const char *t;
  305     char *w;
  306 
  307     if (!sec->auth_ldapgroupkey) return DECLINED; 
  308     if (!reqs_arr) return DECLINED;
  309     for(x=0; x < reqs_arr->nelts; x++) {
  310       
  311     if (! (reqs[x].method_mask & (1 << m))) continue;
  312     
  313         t = reqs[x].requirement;
  314         w = ap_getword(r->pool, &t, ' ');
  315     
  316         if(!strcmp(w,"group") && sec->auth_ldapgroupkey) {
  317            const char *orig_groups,*groups;
  318        char *v;
  319 
  320            if (!(groups = get_ldap_grp(r, user, 0, sec))) {
  321            if (!(sec->auth_ldapauthoritative))
  322                return DECLINED;
  323                ap_snprintf(errstr, sizeof(errstr), 
  324             "groups for user %s not found in LDAP directory (key %s)",
  325             user, sec->auth_ldapgroupkey);
  326            ap_log_reason (errstr, r->filename, r);
  327            ap_note_basic_auth_failure (r);
  328            return AUTH_REQUIRED;
  329            }
  330            orig_groups = groups;
  331            while(t[0]) {
  332                w = ap_getword(r->pool, &t, ' ');
  333                groups = orig_groups;
  334                while(groups[0]) {
  335                    v = ap_getword(r->pool, &groups,',');
  336                    if(!strcmp(v,w))
  337                        return OK;
  338                }
  339            }
  340            ap_snprintf(errstr, sizeof(errstr), 
  341         "user %s not in right group",user);
  342        ap_log_reason (errstr, r->filename, r);
  343            ap_note_basic_auth_failure(r);
  344        return AUTH_REQUIRED;
  345        }
  346     }
  347     
  348     return DECLINED;
  349 }
  350 
  351 
  352 module ldap_auth_module = {
  353    STANDARD_MODULE_STUFF,
  354    NULL,            /* initializer */
  355    create_ldap_auth_dir_config, /* dir config creater */
  356    NULL,            /* dir merger --- default is to override */
  357    NULL,            /* server config */
  358    NULL,            /* merge server config */
  359    ldap_auth_cmds,      /* command table */
  360    NULL,            /* handlers */
  361    NULL,            /* filename translation */
  362    ldap_authenticate_basic_user,    /* check_user_id */
  363    ldap_check_auth,     /* check auth */
  364    NULL,            /* check access */
  365    NULL,            /* type_checker */
  366    NULL,            /* fixups */
  367    NULL,            /* logger */
  368    NULL             /* header parser */
  369 };