Project

General

Profile

Feature #688 » 0003-pam-auth.patch

akschu1, 2018-09-17 19:47

View differences:

lighttpd-1.4.50/configure.ac 2018-09-17 10:50:50.339749492 -0800
425 425
fi
426 426
AM_CONDITIONAL([BUILD_WITH_LDAP], [test "$WITH_LDAP" != no])
427 427

  
428
dnl Check for PAM
429
AC_MSG_CHECKING(for PAM support)
430
AC_ARG_WITH(pam, AC_HELP_STRING([--with-pam],[enable PAM support]),
431
[WITH_PAM=$withval], [WITH_PAM=no])
432
AC_MSG_RESULT([$withval])
433
if test "$WITH_PAM" != "no"; then
434
 AC_CHECK_LIB(pam, pam_start, [
435
  AC_CHECK_HEADERS([security/pam_appl.h],[
436
    PAM_LIB=-lpam
437
    AC_DEFINE([HAVE_LIBPAM], [1], [libpam])
438
    AC_DEFINE([HAVE_SECURITY_PAM_APPL_H], [1])
439
  ])
440
 ])
441
 AC_SUBST(PAM_LIB)
442
fi
443
AM_CONDITIONAL(BUILD_WITH_PAM, test ! $WITH_PAM = no)
444

  
428 445
dnl Check for xattr
429 446
AC_MSG_NOTICE([----------------------------------------])
430 447
AC_MSG_CHECKING([for extended attributes support])
......
1340 1357
  mod_wstunnel \
1341 1358
"
1342 1359

  
1360
plugins="mod_authn_pam"
1361
if test ! "x$PAM_LIB" = x; then
1362
	do_build="$do_build $plugins"
1363
else
1364
	no_build="$no_build $plugins"
1365
fi
1366

  
1343 1367
lighty_track_feature() {
1344 1368
  if eval "$3"; then
1345 1369
    enable_feature="$enable_feature $1"
lighttpd-1.4.50/src/Makefile.am 2018-09-17 10:50:50.346749589 -0800
342 342
mod_authn_ldap_la_LIBADD = $(LDAP_LIB) $(LBER_LIB) $(common_libadd)
343 343
endif
344 344

  
345
if BUILD_WITH_PAM
346
lib_LTLIBRARIES += mod_authn_pam.la
347
mod_authn_pam_la_SOURCES = mod_authn_pam.c
348
mod_authn_pam_la_LDFLAGS = $(common_module_ldflags)
349
mod_authn_pam_la_LIBADD = $(PAM_LIB) $(common_libadd)
350
endif
351

  
345 352
if BUILD_WITH_MYSQL
346 353
lib_LTLIBRARIES += mod_authn_mysql.la
347 354
mod_authn_mysql_la_SOURCES = mod_authn_mysql.c
lighttpd-1.4.50/src/configfile.c 2018-09-17 10:50:50.351749629 -0800
24 24
#include <glob.h>
25 25

  
26 26

  
27
#if defined(HAVE_MYSQL) || (defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER))
27
#if defined(HAVE_LIBPAM) || defined(HAVE_MYSQL) || (defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER))
28 28
static void config_warn_authn_module (server *srv, const char *module) {
29 29
	size_t len = strlen(module);
30 30
	for (size_t i = 0; i < srv->config_context->used; ++i) {
......
553 553
		int append_mod_authn_file = 1;
554 554
		int append_mod_authn_ldap = 1;
555 555
		int append_mod_authn_mysql = 1;
556
		int append_mod_authn_pam = 1;
556 557
		int append_mod_openssl = 1;
557 558
		int contains_mod_auth = 0;
558 559

  
......
588 589
				append_mod_authn_mysql = 0;
589 590
			}
590 591

  
592
			if (buffer_is_equal_string(ds->value, CONST_STR_LEN("mod_authn_pam"))) {
593
				append_mod_authn_pam = 0;
594
			}
595

  
591 596
			if (buffer_is_equal_string(ds->value, CONST_STR_LEN("mod_auth"))) {
592 597
				contains_mod_auth = 1;
593 598
			}
......
599 604
			    0 == append_mod_authn_file &&
600 605
			    0 == append_mod_authn_ldap &&
601 606
			    0 == append_mod_authn_mysql &&
607
			    0 == append_mod_authn_pam &&
602 608
			    1 == contains_mod_auth) {
603 609
				break;
604 610
			}
lighttpd-1.4.50/src/mod_authn_pam.c 2018-09-17 10:51:47.680591497 -0800
1
#include "first.h"
2

  
3
#define USE_PAM
4
#include <security/pam_appl.h>
5

  
6
#include "base.h"
7
#include "http_auth.h"
8
#include "log.h"
9
#include "plugin.h"
10

  
11
#include <errno.h>
12
#include <stdlib.h>
13
#include <string.h>
14

  
15
typedef struct {
16
	buffer *auth_pam_servicename;
17
} plugin_config;
18

  
19
typedef struct {
20
    PLUGIN_DATA;
21
    plugin_config **config_storage;
22
    plugin_config conf, *anon_conf; /* this is only used as long as no handler_ctx is setup */
23
} plugin_data;
24

  
25
static handler_t mod_authn_pam_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw);
26

  
27
INIT_FUNC(mod_authn_pam_init) {
28
    static http_auth_backend_t http_auth_backend_pam =
29
      { "pam", mod_authn_pam_basic, NULL, NULL };
30
    plugin_data *p = calloc(1, sizeof(*p));
31

  
32
    /* register http_auth_backend_pam */
33
    http_auth_backend_pam.p_d = p;
34
    http_auth_backend_set(&http_auth_backend_pam);
35

  
36
    return p;
37
}
38

  
39
FREE_FUNC(mod_authn_pam_free) {
40
    plugin_data *p = p_d;
41

  
42
    UNUSED(srv);
43

  
44
    if (!p) return HANDLER_GO_ON;
45

  
46
    if (p->config_storage) {
47
        size_t i;
48
        for (i = 0; i < srv->config_context->used; i++) {
49
            plugin_config *s = p->config_storage[i];
50

  
51
            if (NULL == s) continue;
52

  
53
            buffer_free(s->auth_pam_servicename);
54
            free(s);
55
        }
56
        free(p->config_storage);
57
    }
58

  
59
    free(p);
60

  
61
    return HANDLER_GO_ON;
62
}
63

  
64
SETDEFAULTS_FUNC(mod_authn_pam_set_defaults) {
65
    plugin_data *p = p_d;
66
    size_t i;
67
config_values_t cv[] = {
68
		{ "auth.backend.pam.service-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
69
        { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
70
    };
71

  
72
    p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
73

  
74
    for (i = 0; i < srv->config_context->used; i++) {
75
        data_config const* config = (data_config const*)srv->config_context->data[i];
76
        plugin_config *s;
77

  
78
        s = calloc(1, sizeof(plugin_config));
79

  
80
        s->auth_pam_servicename = buffer_init();
81

  
82
        cv[0].destination = s->auth_pam_servicename;
83

  
84
        p->config_storage[i] = s;
85

  
86
        if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
87
            return HANDLER_ERROR;
88
        }
89
    }
90

  
91
    return HANDLER_GO_ON;
92
}
93

  
94
#define PATCH(x) \
95
    p->conf.x = s->x;
96
static int mod_authn_pam_patch_connection(server *srv, connection *con, plugin_data *p) {
97
    size_t i, j;
98
    plugin_config *s = p->config_storage[0];
99

  
100
    PATCH(auth_pam_servicename);
101

  
102
    /* skip the first, the global context */
103
    for (i = 1; i < srv->config_context->used; i++) {
104
        data_config *dc = (data_config *)srv->config_context->data[i];
105
        s = p->config_storage[i];
106

  
107
        /* condition didn't match */
108
        if (!config_check_cond(srv, con, dc)) continue;
109

  
110
        /* merge config */
111
        for (j = 0; j < dc->value->used; j++) {
112
            data_unset *du = dc->value->data[j];
113

  
114
            if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.pam.service-name"))) {
115
                PATCH(auth_pam_servicename);
116
            }
117
        }
118
    }
119

  
120
    return 0;
121
}
122
#undef PATCH
123

  
124
typedef struct {
125
    plugin_config *conf;
126
    const char *username;
127
    const char *realm;
128
    const char *password;
129
} mod_auth_pam_data;
130

  
131
static int mod_authn_pam_fn_conv(int num_msg, const struct pam_message **msg, struct pam_response **p_resp, void *appdata_ptr)  {
132
    mod_auth_pam_data *p_pam = (mod_auth_pam_data *)appdata_ptr;
133
    struct pam_response *resp = (struct pam_response *)malloc(num_msg * sizeof(struct pam_response));
134

  
135
    for(int i = 0; i < num_msg; ++i) {
136
        switch(msg[i]->msg_style) {
137
            case PAM_PROMPT_ECHO_OFF:
138
            case PAM_PROMPT_ECHO_ON:
139
                resp[i].resp = strdup(p_pam->password);
140
                resp[i].resp_retcode = 0;
141
                break;
142
            case PAM_ERROR_MSG:
143
            case PAM_TEXT_INFO:
144
            default:
145
                // ignore
146
                resp[i].resp_retcode = 0;
147
                resp[i].resp = NULL;
148
                continue;
149
        }
150
    }
151

  
152
    *p_resp = resp;
153

  
154
    return PAM_SUCCESS;
155
}
156

  
157
static handler_t mod_authn_pam_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw) {
158
    plugin_data *p = (plugin_data *)p_d;
159
    pam_handle_t *pamh = NULL;
160
    mod_auth_pam_data pam_data = {
161
        &p->conf,
162
        username->ptr,
163
        require->realm->ptr,
164
        pw
165
    };
166
    struct pam_conv conv = { mod_authn_pam_fn_conv, &pam_data };
167
    
168
	mod_authn_pam_patch_connection(srv, con, p);
169

  
170
    int retval = pam_start(
171
            !buffer_is_empty(p->conf.auth_pam_servicename) ? p->conf.auth_pam_servicename->ptr : "lighttpd",
172
            username->ptr,
173
            &conv,
174
            &pamh);
175

  
176
    if(retval != PAM_SUCCESS)
177
        goto auth_pam_fail;
178

  
179
    if((retval = pam_authenticate(pamh, PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS)
180
        goto auth_pam_fail;
181

  
182
    if((retval = pam_acct_mgmt(pamh, PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS)
183
        goto auth_pam_fail;
184

  
185
    pam_end(pamh, retval);
186
    return HANDLER_GO_ON;
187

  
188
auth_pam_fail:
189
    log_error_write(srv, __FILE__, __LINE__, "ss", "pam:", pam_strerror(pamh, retval));
190
    pam_end(pamh, retval);
191
    return HANDLER_ERROR;
192
}
193

  
194
int mod_authn_pam_plugin_init(plugin *p);
195
int mod_authn_pam_plugin_init(plugin *p) {
196
    p->version     = LIGHTTPD_VERSION_ID;
197
    p->name        = buffer_init_string("authn_pam");
198
    p->init        = mod_authn_pam_init;
199
    p->set_defaults = mod_authn_pam_set_defaults;
200
    p->cleanup     = mod_authn_pam_free;
201

  
202
    p->data        = NULL;
203

  
204
    return 0;
205
}
lighttpd-1.4.50/src/server.c 2018-09-17 10:50:50.358749597 -0800
578 578
#else
579 579
      "\t- DBI support\n"
580 580
#endif
581
#ifdef HAVE_LIBPAM
582
	  "\t+ PAM support\n"
583
#else
584
	  "\t- PAM support\n"
585
#endif
581 586
#ifdef HAVE_KRB5
582 587
      "\t+ Kerberos support\n"
583 588
#else
(3-3/3)