From b8f04d80278ab97906dd6a3ef0ce83b10217608e Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Wed, 30 Jan 2013 21:43:10 +0100 Subject: [PATCH] Added PAM authentication. --- config.h.in | 3 +++ configure.ac | 30 +++++++++++++++++++++ src/Makefile.am | 4 +-- src/main-auth.c | 35 ++++++++++++++++++------ src/pam.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ src/pam.h | 6 +++++ 6 files changed, 140 insertions(+), 10 deletions(-) create mode 100644 src/pam.c create mode 100644 src/pam.h diff --git a/config.h.in b/config.h.in index 36015537..264e95cb 100644 --- a/config.h.in +++ b/config.h.in @@ -120,6 +120,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H +/* Enable the PAM library */ +#undef HAVE_PAM + /* Define this if pathfind(3) works */ #undef HAVE_PATHFIND diff --git a/configure.ac b/configure.ac index ea833515..f6f4ad2d 100644 --- a/configure.ac +++ b/configure.ac @@ -11,6 +11,9 @@ AC_PROG_CC gl_EARLY AM_PROG_CC_C_O +if [ test "$GCC" = "yes" ];then + CFLAGS="$CFLAGS -Wall" +fi PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3.0.0]) @@ -31,6 +34,22 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([ *** ]])]) LIBS="$oldlibs" +LIBS="$oldlibs -lpam" +AC_MSG_CHECKING([for pam library]) +AC_LINK_IFELSE([AC_LANG_PROGRAM([ + #include ],[ + pam_start(0, 0, 0, 0);])], + [AC_MSG_RESULT(yes) + AC_SUBST([PAM_LIBS], [-lpam]) + AC_SUBST([PAM_CFLAGS], []) + AC_DEFINE([HAVE_PAM], 1, [Enable the PAM library])], + [AC_MSG_RESULT(no) + AC_MSG_ERROR([[ +*** +*** libpam was not found. It is required for building this program. +*** ]])]) +LIBS="$oldlibs" + gl_INIT enable_local_libopts=yes @@ -43,3 +62,14 @@ AC_CONFIG_FILES([ gl/Makefile ]) AC_OUTPUT + +AC_MSG_NOTICE([summary of build options: + + version: ${VERSION} + Host type: ${host} + Install prefix: ${prefix} + Compiler: ${CC} + CFlags: ${CFLAGS} + Library types: Shared=${enable_shared}, Static=${enable_static} +]) + diff --git a/src/Makefile.am b/src/Makefile.am index fa3e6f43..cc5088b7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,12 +8,12 @@ bin_PROGRAMS = ocserv ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \ cookies.c http-parser/http_parser.c \ vpn.h cookies.h tlslib.h http-parser/http_parser.h log.c tun.c tun.h \ - config.c worker-auth.h + config.c worker-auth.h pam.c pam.h ocserv_SOURCES += ocserv-args.def ocserv-args.c ocserv-args.h ocserv_LDADD = ../gl/libgnu.a ../libopts/libopts.a -ocserv_LDADD += $(LIBGNUTLS_LIBS) $(GDBM_LIBS) +ocserv_LDADD += $(LIBGNUTLS_LIBS) $(GDBM_LIBS) $(PAM_LIBS) ocserv-args.c ocserv-args.h: $(srcdir)/ocserv-args.def -autogen ocserv-args.def diff --git a/src/main-auth.c b/src/main-auth.c index 7ffdc4d0..f1068cb6 100644 --- a/src/main-auth.c +++ b/src/main-auth.c @@ -40,6 +40,7 @@ #include #include #include +#include "pam.h" static int send_auth_reply(cmd_auth_reply_t r, struct proc_list_st* proc, struct lease_st* lease) { @@ -138,15 +139,33 @@ static int handle_auth_req(const struct cfg_st *config, struct tun_st *tun, const struct cmd_auth_req_st * req, struct lease_st **lease, char username[MAX_USERNAME_SIZE]) { -int ret; -#warning fix auth - if (strcmp(req->user, "test") == 0 && strcmp(req->pass, "test") == 0) - ret = 0; - else - ret = -1; - - memcpy(username, req->user, MAX_USERNAME_SIZE); +int ret = -1; +unsigned username_set = 0; + if (config->auth_types & AUTH_TYPE_PAM) { + ret = pam_auth_user(req->user, req->pass); + if (ret != 0) + ret = -1; + + memcpy(username, req->user, MAX_USERNAME_SIZE); + username_set = 1; + } + + if (config->auth_types & AUTH_TYPE_CERTIFICATE) { + if (req->tls_auth_ok != 0) { + ret = 0; + } + + if (username_set == 0) + memcpy(username, req->cert_user, MAX_USERNAME_SIZE); + else { + if (strcmp(username, req->cert_user) != 0) { + syslog(LOG_INFO, "User '%s' presented a certificate from user '%s'", username, req->cert_user); + ret = -1; + } + } + } + if (ret == 0) { /* open tun */ ret = open_tun(config, tun, lease); if (ret < 0) diff --git a/src/pam.c b/src/pam.c new file mode 100644 index 00000000..75b82c3f --- /dev/null +++ b/src/pam.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include + +#define APP_NAME PACKAGE + +#define MAX_REPLIES 2 + +struct local_st { + const char* password; + const char* username; +}; + +int dummy_conv(int msg_size, const struct pam_message **msg, + struct pam_response **resp, void *uptr) +{ +struct local_st * l = uptr; +unsigned i; +struct pam_response *replies; + + if (msg_size == 0) + return PAM_SUCCESS; + + replies = calloc(1, msg_size*sizeof(*replies)); + if (replies == NULL) + return PAM_BUF_ERR; + + for (i=0;imsg);*/ + if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF) + replies[i].resp = strdup(l->password); + else if (msg[i]->msg_style == PAM_PROMPT_ECHO_ON) + replies[i].resp = strdup(l->username); + } + + *resp = replies; + return PAM_SUCCESS; +} + +/* Returns 0 if the user is successfully authenticated + */ +int pam_auth_user(const char* user, const char* pass) +{ +pam_handle_t * ph; +int ret, pret; +struct local_st local; +const struct pam_conv dc = { dummy_conv, &local }; + + local.username = user; + local.password = pass; + + pret = pam_start(APP_NAME, user, &dc, &ph); + if (pret != PAM_SUCCESS) { + syslog(LOG_AUTH, "Error in PAM authentication initialization: %s", pam_strerror(ph, pret)); + return -1; + } + + pret = pam_authenticate(ph, PAM_SILENT|PAM_DISALLOW_NULL_AUTHTOK); + if (pret != PAM_SUCCESS) { + syslog(LOG_AUTH, "Error in PAM authentication: %s", pam_strerror(ph, pret)); + ret = -1; + goto fail; + } + + ret = 0; +fail: + pam_end(ph, pret); + return ret; + +} diff --git a/src/pam.h b/src/pam.h new file mode 100644 index 00000000..bdc5f31d --- /dev/null +++ b/src/pam.h @@ -0,0 +1,6 @@ +#ifndef PAM_H +#define PAM_H + +int pam_auth_user(const char* user, const char* pass); + +#endif