Project

General

Profile

Feature #688 » lighttpd-02-pam_auth.patch

sravas, 2014-08-07 23:52

View differences:

configure.ac
212 212
 AC_SUBST(LBER_LIB)
213 213
fi
214 214

  
215
dnl Check for PAM
216
AC_MSG_CHECKING(for PAM support)
217
AC_ARG_WITH(pam, AC_HELP_STRING([--with-pam],[enable PAM support]),
218
[WITH_PAM=$withval], [WITH_PAM=no])
219
AC_MSG_RESULT([$withval])
220
if test "$WITH_PAM" != "no"; then
221
 AC_CHECK_LIB(pam, pam_start, [
222
  AC_CHECK_HEADERS([security/pam_appl.h],[
223
    PAM_LIB=-lpam
224
    AC_DEFINE([HAVE_LIBPAM], [1], [libpam])
225
    AC_DEFINE([HAVE_SECURITY_PAM_APPL_H], [1])
226
  ])
227
 ])
228
 AC_SUBST(PAM_LIB)
229
fi
230

  
215 231
dnl Check for xattr
216 232
AC_MSG_CHECKING(for extended attributes support)
217 233
AC_ARG_WITH(attr, AC_HELP_STRING([--with-attr],[enable extended attribute support]),
......
723 739
	disable_feature="$disable_feature $features"
724 740
fi
725 741

  
742
features="auth-pam"
743
if test ! "x$PAM_LIB" = x; then
744
	enable_feature="$enable_feature $features"
745
else
746
	disable_feature="$disable_feature $features"
747
fi
748

  
726 749
features="network-openssl"
727 750
if test ! "x$SSL_LIB" = x; then
728 751
	enable_feature="$enable_feature $features"
src/Makefile.am
243 243
lib_LTLIBRARIES += mod_auth.la
244 244
mod_auth_la_SOURCES = mod_auth.c http_auth.c
245 245
mod_auth_la_LDFLAGS = -module -export-dynamic -avoid-version
246
mod_auth_la_LIBADD = $(CRYPT_LIB) $(SSL_LIB) $(LDAP_LIB) $(LBER_LIB) $(common_libadd)
246
mod_auth_la_LIBADD = $(CRYPT_LIB) $(SSL_LIB) $(LDAP_LIB) $(LBER_LIB) $(PAM_LIB) $(common_libadd)
247 247

  
248 248
lib_LTLIBRARIES += mod_rewrite.la
249 249
mod_rewrite_la_SOURCES = mod_rewrite.c
src/http_auth.c
315 315
		stream_close(&f);
316 316
	} else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
317 317
		ret = 0;
318
	} else if (p->conf.auth_backend == AUTH_BACKEND_PAM) {
319
		ret = 0;
318 320
	} else {
319 321
		return -1;
320 322
	}
......
629 631
}
630 632
#endif
631 633

  
634
#ifdef USE_PAM
635
// appdata_ptr shall point to mod_auth_pam_data structure
636
static int pam_fn_conv(int num_msg, const struct pam_message **msg, struct pam_response **p_resp, void *appdata_ptr)  {
637
    mod_auth_pam_data *p_pam = (mod_auth_pam_data *)appdata_ptr;
638
    struct pam_response *resp = (struct pam_response *)malloc(num_msg * sizeof(struct pam_response));
639

  
640
    for(int i = 0; i < num_msg; ++i) {
641
        switch(msg[i]->msg_style) {
642
            case PAM_PROMPT_ECHO_OFF:
643
            case PAM_PROMPT_ECHO_ON:
644
                resp[i].resp = strdup(p_pam->password);
645
                resp[i].resp_retcode = 0;
646
                break;
647
            case PAM_ERROR_MSG:
648
            case PAM_TEXT_INFO:
649
            default:
650
                // ignore
651
                resp[i].resp_retcode = 0;
652
                resp[i].resp = NULL;
653
                continue;
654
        }
655
    }
656

  
657
    *p_resp = resp;
658

  
659
    return PAM_SUCCESS;
660
}
661
#endif
662

  
632 663
/**
633 664
 *
634 665
 *
......
834 865

  
835 866
		return 0;
836 867
#endif
837
	}
868
	} else if (p->conf.auth_backend == AUTH_BACKEND_PAM) {
869
#ifdef USE_PAM
870
        pam_handle_t *pamh = NULL;
871
        mod_auth_pam_data pam_data = {
872
            &p->conf,
873
            username->ptr,
874
            realm->ptr,
875
            pw
876
        };
877
        struct pam_conv conv = { pam_fn_conv, &pam_data };
878

  
879
        int retval = pam_start(
880
                !buffer_is_empty(p->conf.auth_pam_servicename) ? p->conf.auth_pam_servicename->ptr : "lighttpd",
881
                username->ptr,
882
                &conv,
883
                &pamh);
884

  
885
        if(retval != PAM_SUCCESS)
886
            goto auth_pam_fail;
887

  
888
        if((retval = pam_authenticate(pamh, PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS)
889
            goto auth_pam_fail;
890

  
891
        if((retval = pam_acct_mgmt(pamh, PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS)
892
            goto auth_pam_fail;
893

  
894
	    if (p->conf.auth_debug > 1)
895
		    log_error_write(srv, __FILE__, __LINE__, "ss", "pam: authenticated as", username->ptr);
896

  
897
        pam_end(pamh, retval);
898
        return 0;
899

  
900
auth_pam_fail:
901
        log_error_write(srv, __FILE__, __LINE__, "ss", "pam:", pam_strerror(pamh, retval));
902
        pam_end(pamh, retval);
903
        return -1;
904
#endif
905
    }
838 906
	return -1;
839 907
}
840 908

  
src/http_auth.h
9 9
# include <ldap.h>
10 10
#endif
11 11

  
12
#if defined(HAVE_SECURITY_PAM_APPL_H) && defined(HAVE_LIBPAM)
13
# define USE_PAM
14
# include <security/pam_appl.h>
15
#endif
16

  
12 17
typedef enum {
13 18
	AUTH_BACKEND_UNSET,
14 19
	AUTH_BACKEND_PLAIN,
15 20
	AUTH_BACKEND_LDAP,
16 21
	AUTH_BACKEND_HTPASSWD,
17
	AUTH_BACKEND_HTDIGEST
22
	AUTH_BACKEND_HTDIGEST,
23
    AUTH_BACKEND_PAM
18 24
} auth_backend_t;
19 25

  
20 26
typedef struct {
......
38 44
	unsigned short auth_ldap_starttls;
39 45
	unsigned short auth_ldap_allow_empty_pw;
40 46

  
47
    buffer *auth_pam_servicename;
48

  
41 49
	unsigned short auth_debug;
42 50

  
43 51
	/* generated */
......
66 74
	mod_auth_plugin_config conf, *anon_conf; /* this is only used as long as no handler_ctx is setup */
67 75
} mod_auth_plugin_data;
68 76

  
77
typedef struct {
78
    mod_auth_plugin_config *conf;
79
    const char *username;
80
    const char *realm;
81
    const char *password;
82
} mod_auth_pam_data;
83

  
69 84
int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, const char *realm_str);
70 85
int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, const char *realm_str);
71 86
int http_auth_digest_generate_nonce(server *srv, mod_auth_plugin_data *p, buffer *fn, char hh[33]);
src/mod_auth.c
76 76
			buffer_free(s->auth_ldap_filter);
77 77
			buffer_free(s->auth_ldap_cafile);
78 78

  
79
            buffer_free(s->auth_pam_servicename);
80

  
79 81
#ifdef USE_LDAP
80 82
			buffer_free(s->ldap_filter_pre);
81 83
			buffer_free(s->ldap_filter_post);
......
114 116
	PATCH(auth_ldap_cafile);
115 117
	PATCH(auth_ldap_starttls);
116 118
	PATCH(auth_ldap_allow_empty_pw);
119
    PATCH(auth_pam_servicename);
117 120
#ifdef USE_LDAP
118 121
	p->anon_conf = s;
119 122
	PATCH(ldap_filter_pre);
......
169 172
				PATCH(auth_ldap_bindpw);
170 173
			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.allow-empty-pw"))) {
171 174
				PATCH(auth_ldap_allow_empty_pw);
172
			}
175
			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.pam.service-name"))) {
176
                PATCH(auth_pam_servicename);
177
            }
173 178
		}
174 179
	}
175 180

  
......
361 366
		{ "auth.backend.htdigest.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
362 367
		{ "auth.backend.htpasswd.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
363 368
		{ "auth.debug",                     NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },  /* 14 */
369
		{ "auth.backend.pam.service-name",  NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 15 */
364 370
		{ NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
365 371
	};
366 372

  
......
386 392
		s->auth_ldap_filter = buffer_init();
387 393
		s->auth_ldap_cafile = buffer_init();
388 394
		s->auth_ldap_starttls = 0;
395
        s->auth_pam_servicename = buffer_init();
389 396
		s->auth_debug = 0;
390 397

  
391 398
		s->auth_require = array_init();
......
411 418
		cv[12].destination = s->auth_htdigest_userfile;
412 419
		cv[13].destination = s->auth_htpasswd_userfile;
413 420
		cv[14].destination = &(s->auth_debug);
421
        cv[15].destination = s->auth_pam_servicename;
414 422

  
415 423
		p->config_storage[i] = s;
416 424
		ca = ((data_config *)srv->config_context->data[i])->value;
......
428 436
				s->auth_backend = AUTH_BACKEND_PLAIN;
429 437
			} else if (0 == strcmp(s->auth_backend_conf->ptr, "ldap")) {
430 438
				s->auth_backend = AUTH_BACKEND_LDAP;
439
			} else if (0 == strcmp(s->auth_backend_conf->ptr, "pam")) {
440
				s->auth_backend = AUTH_BACKEND_PAM;
431 441
			} else {
432 442
				log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
433 443

  
434
- 
(1-1/3)