diff options
author | Alberto Gonzalez Iniesta <agi@inittab.org> | 2016-12-27 18:25:47 +0100 |
---|---|---|
committer | Alberto Gonzalez Iniesta <agi@inittab.org> | 2016-12-27 18:25:47 +0100 |
commit | 79f3537f69e125f19f59c36aa090120a63186a54 (patch) | |
tree | 2089a3b7dac990841dbc2e4d9b2f535b82dbb0af /src/plugins/auth-pam/auth-pam.c | |
parent | f2137fedb30cb87448eb03b2f288920df6187571 (diff) | |
parent | 3a2bbdb05ca6a6996e424c9fb225cb0d53804125 (diff) |
Merge tag 'upstream/2.4.0'
Upstream version 2.4.0
Diffstat (limited to 'src/plugins/auth-pam/auth-pam.c')
-rw-r--r-- | src/plugins/auth-pam/auth-pam.c | 1028 |
1 files changed, 550 insertions, 478 deletions
diff --git a/src/plugins/auth-pam/auth-pam.c b/src/plugins/auth-pam/auth-pam.c index 5ad3ec8..d3e2c89 100644 --- a/src/plugins/auth-pam/auth-pam.c +++ b/src/plugins/auth-pam/auth-pam.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -68,14 +68,14 @@ */ struct auth_pam_context { - /* Foreground's socket to background process */ - int foreground_fd; + /* Foreground's socket to background process */ + int foreground_fd; - /* Process ID of background process */ - pid_t background_pid; + /* Process ID of background process */ + pid_t background_pid; - /* Verbosity level of OpenVPN */ - int verb; + /* Verbosity level of OpenVPN */ + int verb; }; /* @@ -90,13 +90,13 @@ struct auth_pam_context #define N_NAME_VALUE 16 struct name_value { - const char *name; - const char *value; + const char *name; + const char *value; }; struct name_value_list { - int len; - struct name_value data[N_NAME_VALUE]; + int len; + struct name_value data[N_NAME_VALUE]; }; /* @@ -104,17 +104,17 @@ struct name_value_list { * to the PAM conversation function. */ struct user_pass { - int verb; + int verb; - char username[128]; - char password[128]; - char common_name[128]; + char username[128]; + char password[128]; + char common_name[128]; - const struct name_value_list *name_value_list; + const struct name_value_list *name_value_list; }; /* Background process function */ -static void pam_server (int fd, const char *service, int verb, const struct name_value_list *name_value_list); +static void pam_server(int fd, const char *service, int verb, const struct name_value_list *name_value_list); /* @@ -122,54 +122,66 @@ static void pam_server (int fd, const char *service, int verb, const struct name */ static int -recv_control (int fd) +recv_control(int fd) { - unsigned char c; - const ssize_t size = read (fd, &c, sizeof (c)); - if (size == sizeof (c)) - return c; - else + unsigned char c; + const ssize_t size = read(fd, &c, sizeof(c)); + if (size == sizeof(c)) { - /*fprintf (stderr, "AUTH-PAM: DEBUG recv_control.read=%d\n", (int)size);*/ - return -1; + return c; + } + else + { + /*fprintf (stderr, "AUTH-PAM: DEBUG recv_control.read=%d\n", (int)size);*/ + return -1; } } static int -send_control (int fd, int code) +send_control(int fd, int code) { - unsigned char c = (unsigned char) code; - const ssize_t size = write (fd, &c, sizeof (c)); - if (size == sizeof (c)) - return (int) size; - else - return -1; + unsigned char c = (unsigned char) code; + const ssize_t size = write(fd, &c, sizeof(c)); + if (size == sizeof(c)) + { + return (int) size; + } + else + { + return -1; + } } static int -recv_string (int fd, char *buffer, int len) +recv_string(int fd, char *buffer, int len) { - if (len > 0) + if (len > 0) { - ssize_t size; - memset (buffer, 0, len); - size = read (fd, buffer, len); - buffer[len-1] = 0; - if (size >= 1) - return (int)size; + ssize_t size; + memset(buffer, 0, len); + size = read(fd, buffer, len); + buffer[len-1] = 0; + if (size >= 1) + { + return (int)size; + } } - return -1; + return -1; } static int -send_string (int fd, const char *string) +send_string(int fd, const char *string) { - const int len = strlen (string) + 1; - const ssize_t size = write (fd, string, len); - if (size == len) - return (int) size; - else - return -1; + const int len = strlen(string) + 1; + const ssize_t size = write(fd, string, len); + if (size == len) + { + return (int) size; + } + else + { + return -1; + } } #ifdef DO_DAEMONIZE @@ -180,28 +192,30 @@ send_string (int fd, const char *string) * "daemon_log_redirect" env var is true. */ static void -daemonize (const char *envp[]) +daemonize(const char *envp[]) { - const char *daemon_string = get_env ("daemon", envp); - if (daemon_string && daemon_string[0] == '1') - { - const char *log_redirect = get_env ("daemon_log_redirect", envp); - int fd = -1; - if (log_redirect && log_redirect[0] == '1') - fd = dup (2); - if (daemon (0, 0) < 0) - { - fprintf (stderr, "AUTH-PAM: daemonization failed\n"); - } - else if (fd >= 3) - { - dup2 (fd, 2); - close (fd); - } + const char *daemon_string = get_env("daemon", envp); + if (daemon_string && daemon_string[0] == '1') + { + const char *log_redirect = get_env("daemon_log_redirect", envp); + int fd = -1; + if (log_redirect && log_redirect[0] == '1') + { + fd = dup(2); + } + if (daemon(0, 0) < 0) + { + fprintf(stderr, "AUTH-PAM: daemonization failed\n"); + } + else if (fd >= 3) + { + dup2(fd, 2); + close(fd); + } } } -#endif +#endif /* ifdef DO_DAEMONIZE */ /* * Close most of parent's fds. @@ -214,14 +228,16 @@ daemonize (const char *envp[]) * fds from crossing a fork(). */ static void -close_fds_except (int keep) +close_fds_except(int keep) { - int i; - closelog (); - for (i = 3; i <= 100; ++i) + int i; + closelog(); + for (i = 3; i <= 100; ++i) { - if (i != keep) - close (i); + if (i != keep) + { + close(i); + } } } @@ -230,243 +246,263 @@ close_fds_except (int keep) * deal with them. */ static void -set_signals (void) +set_signals(void) { - signal (SIGTERM, SIG_DFL); + signal(SIGTERM, SIG_DFL); - signal (SIGINT, SIG_IGN); - signal (SIGHUP, SIG_IGN); - signal (SIGUSR1, SIG_IGN); - signal (SIGUSR2, SIG_IGN); - signal (SIGPIPE, SIG_IGN); + signal(SIGINT, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGUSR1, SIG_IGN); + signal(SIGUSR2, SIG_IGN); + signal(SIGPIPE, SIG_IGN); } /* * Return 1 if query matches match. */ static int -name_value_match (const char *query, const char *match) +name_value_match(const char *query, const char *match) { - while (!isalnum (*query)) + while (!isalnum(*query)) { - if (*query == '\0') - return 0; - ++query; + if (*query == '\0') + { + return 0; + } + ++query; } - return strncasecmp (match, query, strlen (match)) == 0; + return strncasecmp(match, query, strlen(match)) == 0; } OPENVPN_EXPORT openvpn_plugin_handle_t -openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[]) +openvpn_plugin_open_v1(unsigned int *type_mask, const char *argv[], const char *envp[]) { - pid_t pid; - int fd[2]; - - struct auth_pam_context *context; - struct name_value_list name_value_list; - - const int base_parms = 2; - - /* - * Allocate our context - */ - context = (struct auth_pam_context *) calloc (1, sizeof (struct auth_pam_context)); - if (!context) - goto error; - context->foreground_fd = -1; - - /* - * Intercept the --auth-user-pass-verify callback. - */ - *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY); + pid_t pid; + int fd[2]; + + struct auth_pam_context *context; + struct name_value_list name_value_list; - /* - * Make sure we have two string arguments: the first is the .so name, - * the second is the PAM service type. - */ - if (string_array_len (argv) < base_parms) + const int base_parms = 2; + + /* + * Allocate our context + */ + context = (struct auth_pam_context *) calloc(1, sizeof(struct auth_pam_context)); + if (!context) { - fprintf (stderr, "AUTH-PAM: need PAM service parameter\n"); - goto error; + goto error; } - - /* - * See if we have optional name/value pairs to match against - * PAM module queried fields in the conversation function. - */ - name_value_list.len = 0; - if (string_array_len (argv) > base_parms) + context->foreground_fd = -1; + + /* + * Intercept the --auth-user-pass-verify callback. + */ + *type_mask = OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY); + + /* + * Make sure we have two string arguments: the first is the .so name, + * the second is the PAM service type. + */ + if (string_array_len(argv) < base_parms) { - const int nv_len = string_array_len (argv) - base_parms; - int i; - - if ((nv_len & 1) == 1 || (nv_len / 2) > N_NAME_VALUE) - { - fprintf (stderr, "AUTH-PAM: bad name/value list length\n"); - goto error; - } - - name_value_list.len = nv_len / 2; - for (i = 0; i < name_value_list.len; ++i) - { - const int base = base_parms + i * 2; - name_value_list.data[i].name = argv[base]; - name_value_list.data[i].value = argv[base+1]; - } + fprintf(stderr, "AUTH-PAM: need PAM service parameter\n"); + goto error; } - /* - * Get verbosity level from environment - */ - { - const char *verb_string = get_env ("verb", envp); - if (verb_string) - context->verb = atoi (verb_string); - } - - /* - * Make a socket for foreground and background processes - * to communicate. - */ - if (socketpair (PF_UNIX, SOCK_DGRAM, 0, fd) == -1) + /* + * See if we have optional name/value pairs to match against + * PAM module queried fields in the conversation function. + */ + name_value_list.len = 0; + if (string_array_len(argv) > base_parms) { - fprintf (stderr, "AUTH-PAM: socketpair call failed\n"); - goto error; + const int nv_len = string_array_len(argv) - base_parms; + int i; + + if ((nv_len & 1) == 1 || (nv_len / 2) > N_NAME_VALUE) + { + fprintf(stderr, "AUTH-PAM: bad name/value list length\n"); + goto error; + } + + name_value_list.len = nv_len / 2; + for (i = 0; i < name_value_list.len; ++i) + { + const int base = base_parms + i * 2; + name_value_list.data[i].name = argv[base]; + name_value_list.data[i].value = argv[base+1]; + } } - /* - * Fork off the privileged process. It will remain privileged - * even after the foreground process drops its privileges. - */ - pid = fork (); - - if (pid) + /* + * Get verbosity level from environment + */ { - int status; - - /* - * Foreground Process - */ - - context->background_pid = pid; + const char *verb_string = get_env("verb", envp); + if (verb_string) + { + context->verb = atoi(verb_string); + } + } - /* close our copy of child's socket */ - close (fd[1]); + /* + * Make a socket for foreground and background processes + * to communicate. + */ + if (socketpair(PF_UNIX, SOCK_DGRAM, 0, fd) == -1) + { + fprintf(stderr, "AUTH-PAM: socketpair call failed\n"); + goto error; + } - /* don't let future subprocesses inherit child socket */ - if (fcntl (fd[0], F_SETFD, FD_CLOEXEC) < 0) - fprintf (stderr, "AUTH-PAM: Set FD_CLOEXEC flag on socket file descriptor failed\n"); + /* + * Fork off the privileged process. It will remain privileged + * even after the foreground process drops its privileges. + */ + pid = fork(); - /* wait for background child process to initialize */ - status = recv_control (fd[0]); - if (status == RESPONSE_INIT_SUCCEEDED) - { - context->foreground_fd = fd[0]; - return (openvpn_plugin_handle_t) context; - } + if (pid) + { + int status; + + /* + * Foreground Process + */ + + context->background_pid = pid; + + /* close our copy of child's socket */ + close(fd[1]); + + /* don't let future subprocesses inherit child socket */ + if (fcntl(fd[0], F_SETFD, FD_CLOEXEC) < 0) + { + fprintf(stderr, "AUTH-PAM: Set FD_CLOEXEC flag on socket file descriptor failed\n"); + } + + /* wait for background child process to initialize */ + status = recv_control(fd[0]); + if (status == RESPONSE_INIT_SUCCEEDED) + { + context->foreground_fd = fd[0]; + return (openvpn_plugin_handle_t) context; + } } - else + else { - /* - * Background Process - */ + /* + * Background Process + */ - /* close all parent fds except our socket back to parent */ - close_fds_except (fd[1]); + /* close all parent fds except our socket back to parent */ + close_fds_except(fd[1]); - /* Ignore most signals (the parent will receive them) */ - set_signals (); + /* Ignore most signals (the parent will receive them) */ + set_signals(); #ifdef DO_DAEMONIZE - /* Daemonize if --daemon option is set. */ - daemonize (envp); + /* Daemonize if --daemon option is set. */ + daemonize(envp); #endif - /* execute the event loop */ - pam_server (fd[1], argv[1], context->verb, &name_value_list); + /* execute the event loop */ + pam_server(fd[1], argv[1], context->verb, &name_value_list); - close (fd[1]); + close(fd[1]); - exit (0); - return 0; /* NOTREACHED */ + exit(0); + return 0; /* NOTREACHED */ } - error: - if (context) - free (context); - return NULL; +error: + if (context) + { + free(context); + } + return NULL; } OPENVPN_EXPORT int -openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[]) +openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[]) { - struct auth_pam_context *context = (struct auth_pam_context *) handle; - - if (type == OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY && context->foreground_fd >= 0) - { - /* get username/password from envp string array */ - const char *username = get_env ("username", envp); - const char *password = get_env ("password", envp); - const char *common_name = get_env ("common_name", envp) ? get_env ("common_name", envp) : ""; - - if (username && strlen (username) > 0 && password) - { - if (send_control (context->foreground_fd, COMMAND_VERIFY) == -1 - || send_string (context->foreground_fd, username) == -1 - || send_string (context->foreground_fd, password) == -1 - || send_string (context->foreground_fd, common_name) == -1) - { - fprintf (stderr, "AUTH-PAM: Error sending auth info to background process\n"); - } - else - { - const int status = recv_control (context->foreground_fd); - if (status == RESPONSE_VERIFY_SUCCEEDED) - return OPENVPN_PLUGIN_FUNC_SUCCESS; - if (status == -1) - fprintf (stderr, "AUTH-PAM: Error receiving auth confirmation from background process\n"); - } - } - } - return OPENVPN_PLUGIN_FUNC_ERROR; + struct auth_pam_context *context = (struct auth_pam_context *) handle; + + if (type == OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY && context->foreground_fd >= 0) + { + /* get username/password from envp string array */ + const char *username = get_env("username", envp); + const char *password = get_env("password", envp); + const char *common_name = get_env("common_name", envp) ? get_env("common_name", envp) : ""; + + if (username && strlen(username) > 0 && password) + { + if (send_control(context->foreground_fd, COMMAND_VERIFY) == -1 + || send_string(context->foreground_fd, username) == -1 + || send_string(context->foreground_fd, password) == -1 + || send_string(context->foreground_fd, common_name) == -1) + { + fprintf(stderr, "AUTH-PAM: Error sending auth info to background process\n"); + } + else + { + const int status = recv_control(context->foreground_fd); + if (status == RESPONSE_VERIFY_SUCCEEDED) + { + return OPENVPN_PLUGIN_FUNC_SUCCESS; + } + if (status == -1) + { + fprintf(stderr, "AUTH-PAM: Error receiving auth confirmation from background process\n"); + } + } + } + } + return OPENVPN_PLUGIN_FUNC_ERROR; } OPENVPN_EXPORT void -openvpn_plugin_close_v1 (openvpn_plugin_handle_t handle) +openvpn_plugin_close_v1(openvpn_plugin_handle_t handle) { - struct auth_pam_context *context = (struct auth_pam_context *) handle; - - if (DEBUG (context->verb)) - fprintf (stderr, "AUTH-PAM: close\n"); + struct auth_pam_context *context = (struct auth_pam_context *) handle; - if (context->foreground_fd >= 0) + if (DEBUG(context->verb)) { - /* tell background process to exit */ - if (send_control (context->foreground_fd, COMMAND_EXIT) == -1) - fprintf (stderr, "AUTH-PAM: Error signaling background process to exit\n"); - - /* wait for background process to exit */ - if (context->background_pid > 0) - waitpid (context->background_pid, NULL, 0); + fprintf(stderr, "AUTH-PAM: close\n"); + } - close (context->foreground_fd); - context->foreground_fd = -1; + if (context->foreground_fd >= 0) + { + /* tell background process to exit */ + if (send_control(context->foreground_fd, COMMAND_EXIT) == -1) + { + fprintf(stderr, "AUTH-PAM: Error signaling background process to exit\n"); + } + + /* wait for background process to exit */ + if (context->background_pid > 0) + { + waitpid(context->background_pid, NULL, 0); + } + + close(context->foreground_fd); + context->foreground_fd = -1; } - free (context); + free(context); } OPENVPN_EXPORT void -openvpn_plugin_abort_v1 (openvpn_plugin_handle_t handle) +openvpn_plugin_abort_v1(openvpn_plugin_handle_t handle) { - struct auth_pam_context *context = (struct auth_pam_context *) handle; + struct auth_pam_context *context = (struct auth_pam_context *) handle; - /* tell background process to exit */ - if (context && context->foreground_fd >= 0) + /* tell background process to exit */ + if (context && context->foreground_fd >= 0) { - send_control (context->foreground_fd, COMMAND_EXIT); - close (context->foreground_fd); - context->foreground_fd = -1; + send_control(context->foreground_fd, COMMAND_EXIT); + close(context->foreground_fd); + context->foreground_fd = -1; } } @@ -474,111 +510,137 @@ openvpn_plugin_abort_v1 (openvpn_plugin_handle_t handle) * PAM conversation function */ static int -my_conv (int n, const struct pam_message **msg_array, - struct pam_response **response_array, void *appdata_ptr) +my_conv(int n, const struct pam_message **msg_array, + struct pam_response **response_array, void *appdata_ptr) { - const struct user_pass *up = ( const struct user_pass *) appdata_ptr; - struct pam_response *aresp; - int i; - int ret = PAM_SUCCESS; - - *response_array = NULL; - - if (n <= 0 || n > PAM_MAX_NUM_MSG) - return (PAM_CONV_ERR); - if ((aresp = calloc (n, sizeof *aresp)) == NULL) - return (PAM_BUF_ERR); - - /* loop through each PAM-module query */ - for (i = 0; i < n; ++i) - { - const struct pam_message *msg = msg_array[i]; - aresp[i].resp_retcode = 0; - aresp[i].resp = NULL; - - if (DEBUG (up->verb)) - { - fprintf (stderr, "AUTH-PAM: BACKGROUND: my_conv[%d] query='%s' style=%d\n", - i, - msg->msg ? msg->msg : "NULL", - msg->msg_style); - } - - if (up->name_value_list && up->name_value_list->len > 0) - { - /* use name/value list match method */ - const struct name_value_list *list = up->name_value_list; - int j; - - /* loop through name/value pairs */ - for (j = 0; j < list->len; ++j) - { - const char *match_name = list->data[j].name; - const char *match_value = list->data[j].value; - - if (name_value_match (msg->msg, match_name)) - { - /* found name/value match */ - aresp[i].resp = NULL; - - if (DEBUG (up->verb)) - fprintf (stderr, "AUTH-PAM: BACKGROUND: name match found, query/match-string ['%s', '%s'] = '%s'\n", - msg->msg, - match_name, - match_value); - - if (strstr(match_value, "USERNAME")) - aresp[i].resp = searchandreplace(match_value, "USERNAME", up->username); - else if (strstr(match_value, "PASSWORD")) - aresp[i].resp = searchandreplace(match_value, "PASSWORD", up->password); - else if (strstr(match_value, "COMMONNAME")) - aresp[i].resp = searchandreplace(match_value, "COMMONNAME", up->common_name); - else - aresp[i].resp = strdup (match_value); - - if (aresp[i].resp == NULL) - ret = PAM_CONV_ERR; - break; - } - } - - if (j == list->len) - ret = PAM_CONV_ERR; - } - else - { - /* use PAM_PROMPT_ECHO_x hints */ - switch (msg->msg_style) - { - case PAM_PROMPT_ECHO_OFF: - aresp[i].resp = strdup (up->password); - if (aresp[i].resp == NULL) - ret = PAM_CONV_ERR; - break; - - case PAM_PROMPT_ECHO_ON: - aresp[i].resp = strdup (up->username); - if (aresp[i].resp == NULL) - ret = PAM_CONV_ERR; - break; - - case PAM_ERROR_MSG: - case PAM_TEXT_INFO: - break; - - default: - ret = PAM_CONV_ERR; - break; - } - } - } - - if (ret == PAM_SUCCESS) - *response_array = aresp; - else - free(aresp); - - return ret; + const struct user_pass *up = ( const struct user_pass *) appdata_ptr; + struct pam_response *aresp; + int i; + int ret = PAM_SUCCESS; + + *response_array = NULL; + + if (n <= 0 || n > PAM_MAX_NUM_MSG) + { + return (PAM_CONV_ERR); + } + if ((aresp = calloc(n, sizeof *aresp)) == NULL) + { + return (PAM_BUF_ERR); + } + + /* loop through each PAM-module query */ + for (i = 0; i < n; ++i) + { + const struct pam_message *msg = msg_array[i]; + aresp[i].resp_retcode = 0; + aresp[i].resp = NULL; + + if (DEBUG(up->verb)) + { + fprintf(stderr, "AUTH-PAM: BACKGROUND: my_conv[%d] query='%s' style=%d\n", + i, + msg->msg ? msg->msg : "NULL", + msg->msg_style); + } + + if (up->name_value_list && up->name_value_list->len > 0) + { + /* use name/value list match method */ + const struct name_value_list *list = up->name_value_list; + int j; + + /* loop through name/value pairs */ + for (j = 0; j < list->len; ++j) + { + const char *match_name = list->data[j].name; + const char *match_value = list->data[j].value; + + if (name_value_match(msg->msg, match_name)) + { + /* found name/value match */ + aresp[i].resp = NULL; + + if (DEBUG(up->verb)) + { + fprintf(stderr, "AUTH-PAM: BACKGROUND: name match found, query/match-string ['%s', '%s'] = '%s'\n", + msg->msg, + match_name, + match_value); + } + + if (strstr(match_value, "USERNAME")) + { + aresp[i].resp = searchandreplace(match_value, "USERNAME", up->username); + } + else if (strstr(match_value, "PASSWORD")) + { + aresp[i].resp = searchandreplace(match_value, "PASSWORD", up->password); + } + else if (strstr(match_value, "COMMONNAME")) + { + aresp[i].resp = searchandreplace(match_value, "COMMONNAME", up->common_name); + } + else + { + aresp[i].resp = strdup(match_value); + } + + if (aresp[i].resp == NULL) + { + ret = PAM_CONV_ERR; + } + break; + } + } + + if (j == list->len) + { + ret = PAM_CONV_ERR; + } + } + else + { + /* use PAM_PROMPT_ECHO_x hints */ + switch (msg->msg_style) + { + case PAM_PROMPT_ECHO_OFF: + aresp[i].resp = strdup(up->password); + if (aresp[i].resp == NULL) + { + ret = PAM_CONV_ERR; + } + break; + + case PAM_PROMPT_ECHO_ON: + aresp[i].resp = strdup(up->username); + if (aresp[i].resp == NULL) + { + ret = PAM_CONV_ERR; + } + break; + + case PAM_ERROR_MSG: + case PAM_TEXT_INFO: + break; + + default: + ret = PAM_CONV_ERR; + break; + } + } + } + + if (ret == PAM_SUCCESS) + { + *response_array = aresp; + } + else + { + free(aresp); + } + + return ret; } /* @@ -587,156 +649,166 @@ my_conv (int n, const struct pam_message **msg_array, * to be authenticated. */ static int -pam_auth (const char *service, const struct user_pass *up) +pam_auth(const char *service, const struct user_pass *up) { - struct pam_conv conv; - pam_handle_t *pamh = NULL; - int status = PAM_SUCCESS; - int ret = 0; - const int name_value_list_provided = (up->name_value_list && up->name_value_list->len > 0); - - /* Initialize PAM */ - conv.conv = my_conv; - conv.appdata_ptr = (void *)up; - status = pam_start (service, name_value_list_provided ? NULL : up->username, &conv, &pamh); - if (status == PAM_SUCCESS) - { - /* Call PAM to verify username/password */ - status = pam_authenticate(pamh, 0); - if (status == PAM_SUCCESS) - status = pam_acct_mgmt (pamh, 0); - if (status == PAM_SUCCESS) - ret = 1; - - /* Output error message if failed */ - if (!ret) - { - fprintf (stderr, "AUTH-PAM: BACKGROUND: user '%s' failed to authenticate: %s\n", - up->username, - pam_strerror (pamh, status)); - } - - /* Close PAM */ - pam_end (pamh, status); - } - - return ret; + struct pam_conv conv; + pam_handle_t *pamh = NULL; + int status = PAM_SUCCESS; + int ret = 0; + const int name_value_list_provided = (up->name_value_list && up->name_value_list->len > 0); + + /* Initialize PAM */ + conv.conv = my_conv; + conv.appdata_ptr = (void *)up; + status = pam_start(service, name_value_list_provided ? NULL : up->username, &conv, &pamh); + if (status == PAM_SUCCESS) + { + /* Call PAM to verify username/password */ + status = pam_authenticate(pamh, 0); + if (status == PAM_SUCCESS) + { + status = pam_acct_mgmt(pamh, 0); + } + if (status == PAM_SUCCESS) + { + ret = 1; + } + + /* Output error message if failed */ + if (!ret) + { + fprintf(stderr, "AUTH-PAM: BACKGROUND: user '%s' failed to authenticate: %s\n", + up->username, + pam_strerror(pamh, status)); + } + + /* Close PAM */ + pam_end(pamh, status); + } + + return ret; } /* * Background process -- runs with privilege. */ static void -pam_server (int fd, const char *service, int verb, const struct name_value_list *name_value_list) +pam_server(int fd, const char *service, int verb, const struct name_value_list *name_value_list) { - struct user_pass up; - int command; + struct user_pass up; + int command; #ifdef USE_PAM_DLOPEN - static const char pam_so[] = "libpam.so"; + static const char pam_so[] = "libpam.so"; #endif - /* - * Do initialization - */ - if (DEBUG (verb)) - fprintf (stderr, "AUTH-PAM: BACKGROUND: INIT service='%s'\n", service); + /* + * Do initialization + */ + if (DEBUG(verb)) + { + fprintf(stderr, "AUTH-PAM: BACKGROUND: INIT service='%s'\n", service); + } #ifdef USE_PAM_DLOPEN - /* - * Load PAM shared object - */ - if (!dlopen_pam (pam_so)) + /* + * Load PAM shared object + */ + if (!dlopen_pam(pam_so)) { - fprintf (stderr, "AUTH-PAM: BACKGROUND: could not load PAM lib %s: %s\n", pam_so, dlerror()); - send_control (fd, RESPONSE_INIT_FAILED); - goto done; + fprintf(stderr, "AUTH-PAM: BACKGROUND: could not load PAM lib %s: %s\n", pam_so, dlerror()); + send_control(fd, RESPONSE_INIT_FAILED); + goto done; } #endif - /* - * Tell foreground that we initialized successfully - */ - if (send_control (fd, RESPONSE_INIT_SUCCEEDED) == -1) + /* + * Tell foreground that we initialized successfully + */ + if (send_control(fd, RESPONSE_INIT_SUCCEEDED) == -1) { - fprintf (stderr, "AUTH-PAM: BACKGROUND: write error on response socket [1]\n"); - goto done; + fprintf(stderr, "AUTH-PAM: BACKGROUND: write error on response socket [1]\n"); + goto done; } - /* - * Event loop - */ - while (1) + /* + * Event loop + */ + while (1) { - memset (&up, 0, sizeof (up)); - up.verb = verb; - up.name_value_list = name_value_list; - - /* get a command from foreground process */ - command = recv_control (fd); - - if (DEBUG (verb)) - fprintf (stderr, "AUTH-PAM: BACKGROUND: received command code: %d\n", command); - - switch (command) - { - case COMMAND_VERIFY: - if (recv_string (fd, up.username, sizeof (up.username)) == -1 - || recv_string (fd, up.password, sizeof (up.password)) == -1 - || recv_string (fd, up.common_name, sizeof (up.common_name)) == -1) - { - fprintf (stderr, "AUTH-PAM: BACKGROUND: read error on command channel: code=%d, exiting\n", - command); - goto done; - } - - if (DEBUG (verb)) - { + memset(&up, 0, sizeof(up)); + up.verb = verb; + up.name_value_list = name_value_list; + + /* get a command from foreground process */ + command = recv_control(fd); + + if (DEBUG(verb)) + { + fprintf(stderr, "AUTH-PAM: BACKGROUND: received command code: %d\n", command); + } + + switch (command) + { + case COMMAND_VERIFY: + if (recv_string(fd, up.username, sizeof(up.username)) == -1 + || recv_string(fd, up.password, sizeof(up.password)) == -1 + || recv_string(fd, up.common_name, sizeof(up.common_name)) == -1) + { + fprintf(stderr, "AUTH-PAM: BACKGROUND: read error on command channel: code=%d, exiting\n", + command); + goto done; + } + + if (DEBUG(verb)) + { #if 0 - fprintf (stderr, "AUTH-PAM: BACKGROUND: USER/PASS: %s/%s\n", - up.username, up.password); + fprintf(stderr, "AUTH-PAM: BACKGROUND: USER/PASS: %s/%s\n", + up.username, up.password); #else - fprintf (stderr, "AUTH-PAM: BACKGROUND: USER: %s\n", up.username); + fprintf(stderr, "AUTH-PAM: BACKGROUND: USER: %s\n", up.username); #endif - } - - if (pam_auth (service, &up)) /* Succeeded */ - { - if (send_control (fd, RESPONSE_VERIFY_SUCCEEDED) == -1) - { - fprintf (stderr, "AUTH-PAM: BACKGROUND: write error on response socket [2]\n"); - goto done; - } - } - else /* Failed */ - { - if (send_control (fd, RESPONSE_VERIFY_FAILED) == -1) - { - fprintf (stderr, "AUTH-PAM: BACKGROUND: write error on response socket [3]\n"); - goto done; - } - } - break; - - case COMMAND_EXIT: - goto done; - - case -1: - fprintf (stderr, "AUTH-PAM: BACKGROUND: read error on command channel\n"); - goto done; - - default: - fprintf (stderr, "AUTH-PAM: BACKGROUND: unknown command code: code=%d, exiting\n", - command); - goto done; - } - } - done: + } + + if (pam_auth(service, &up)) /* Succeeded */ + { + if (send_control(fd, RESPONSE_VERIFY_SUCCEEDED) == -1) + { + fprintf(stderr, "AUTH-PAM: BACKGROUND: write error on response socket [2]\n"); + goto done; + } + } + else /* Failed */ + { + if (send_control(fd, RESPONSE_VERIFY_FAILED) == -1) + { + fprintf(stderr, "AUTH-PAM: BACKGROUND: write error on response socket [3]\n"); + goto done; + } + } + break; + + case COMMAND_EXIT: + goto done; + + case -1: + fprintf(stderr, "AUTH-PAM: BACKGROUND: read error on command channel\n"); + goto done; + + default: + fprintf(stderr, "AUTH-PAM: BACKGROUND: unknown command code: code=%d, exiting\n", + command); + goto done; + } + } +done: #ifdef USE_PAM_DLOPEN - dlclose_pam (); + dlclose_pam(); #endif - if (DEBUG (verb)) - fprintf (stderr, "AUTH-PAM: BACKGROUND: EXIT\n"); + if (DEBUG(verb)) + { + fprintf(stderr, "AUTH-PAM: BACKGROUND: EXIT\n"); + } - return; + return; } |