1/* 2 * Copyright (C) 2002-2009 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms of pam_uwtmp, with 5 * or without modification, are permitted provided that the following 6 * conditions are met: 7 * 8 * 1. Redistributions of source code must retain any existing copyright 9 * notice, and this entire permission notice in its entirety, 10 * including the disclaimer of warranties. 11 * 12 * 2. Redistributions in binary form must reproduce all prior and current 13 * copyright notices, this list of conditions, and the following 14 * disclaimer in the documentation and/or other materials provided 15 * with the distribution. 16 * 17 * 3. The name of any author may not be used to endorse or promote 18 * products derived from this software without their specific prior 19 * written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 29 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 30 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 * DAMAGE. 32 */ 33 34#include <sys/types.h> 35#include <sys/time.h> 36#include <unistd.h> 37#include <utmpx.h> 38#include <string.h> 39#include <stdlib.h> 40 41#define PAM_SM_SESSION 42#include <security/pam_modules.h> 43#include <security/pam_appl.h> 44#include <security/openpam.h> 45 46#define DATA_NAME "pam_uwtmp.utmpx" 47 48PAM_EXTERN int 49populate_struct(pam_handle_t *pamh, struct utmpx *u) 50{ 51 int status; 52 char *tty; 53 char *user; 54 char *remhost; 55 56 if (NULL == u) 57 return PAM_SYSTEM_ERR; 58 59 if (PAM_SUCCESS != (status = pam_get_item(pamh, PAM_USER, (const void **)&user))) { 60 openpam_log(PAM_LOG_DEBUG, "Unable to obtain the username."); 61 return status; 62 } 63 if (NULL != user) 64 strlcpy(u->ut_user, user, sizeof(u->ut_user)); 65 66 if (PAM_SUCCESS != (status = pam_get_item(pamh, PAM_TTY, (const void **)&tty))) { 67 openpam_log(PAM_LOG_DEBUG, "Unable to obtain the tty."); 68 return status; 69 } 70 if (NULL == tty) { 71 openpam_log(PAM_LOG_DEBUG, "The tty is NULL."); 72 return PAM_IGNORE; 73 } else 74 strlcpy(u->ut_line, tty, sizeof(u->ut_line)); 75 76 if (PAM_SUCCESS != (status = pam_get_item(pamh, PAM_RHOST, (const void **)&remhost))) { 77 openpam_log(PAM_LOG_DEBUG, "Unable to obtain the rhost."); 78 return status; 79 } 80 if (NULL != remhost) 81 strlcpy(u->ut_host, remhost, sizeof(u->ut_host)); 82 83 return status; 84} 85 86PAM_EXTERN int 87pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) 88{ 89 int status; 90 struct utmpx *u = NULL; 91 92 if( (u = calloc(1, sizeof(*u))) == NULL ) { 93 openpam_log(PAM_LOG_ERROR, "Memory allocation error."); 94 return PAM_BUF_ERR; 95 } 96 97 if (PAM_SUCCESS != (status = populate_struct(pamh, u))) { 98 pam_set_data(pamh, DATA_NAME, NULL, NULL); 99 goto err; 100 } 101 102 u->ut_pid = getpid(); 103 u->ut_type = UTMPX_AUTOFILL_MASK | USER_PROCESS; 104 gettimeofday(&u->ut_tv, NULL); 105 106 if (PAM_SUCCESS != (status = pam_set_data(pamh, DATA_NAME, u, openpam_free_data))) { 107 openpam_log(PAM_LOG_ERROR, "There was an error setting data in the context."); 108 goto err; 109 } 110 111 if( pututxline(u) == NULL ) { 112 openpam_log(PAM_LOG_ERROR, "Unable to write the utmp record."); 113 status = PAM_SYSTEM_ERR; 114 goto err; 115 } 116 117 return PAM_SUCCESS; 118 119err: 120 free(u); 121 return status; 122} 123 124PAM_EXTERN int 125pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) 126{ 127 int status; 128 struct utmpx *u = NULL; 129 int free_u = 0; 130 131 status = pam_get_data(pamh, DATA_NAME, (const void **)&u); 132 if( status != PAM_SUCCESS ) { 133 openpam_log(PAM_LOG_DEBUG, "Unable to obtain the tmp record from the context."); 134 } 135 136 if (NULL == u) { 137 if( (u = calloc(1, sizeof(*u))) == NULL ) { 138 openpam_log(PAM_LOG_ERROR, "Memory allocation error."); 139 return PAM_BUF_ERR; 140 } 141 free_u = 1; 142 143 if (PAM_SUCCESS != (status = populate_struct(pamh, u))) 144 goto fin; 145 } 146 147 u->ut_pid = getpid(); 148 u->ut_type = UTMPX_AUTOFILL_MASK | DEAD_PROCESS; 149 gettimeofday(&u->ut_tv, NULL); 150 151 if( pututxline(u) == NULL ) { 152 openpam_log(PAM_LOG_ERROR, "Unable to write the utmp record."); 153 status = PAM_SYSTEM_ERR; 154 goto fin; 155 } 156 157 status = PAM_SUCCESS; 158 159fin: 160 if (1 == free_u) 161 free(u); 162 return status; 163} 164