1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 /* 30 * University Copyright- Copyright (c) 1982, 1986, 1988 31 * The Regents of the University of California 32 * All Rights Reserved 33 * 34 * University Acknowledgment- Portions of this document are derived from 35 * software developed by the University of California, Berkeley, and its 36 * contributors. 37 */ 38 39 #pragma ident "%Z%%M% %I% %E% SMI" 40 41 #include <unistd.h> 42 #include <stdlib.h> 43 #include <stdio.h> 44 #include <fcntl.h> 45 #include <sys/types.h> 46 #include <sys/wait.h> 47 #include <string.h> 48 #include <memory.h> 49 #include <utmpx.h> 50 #include <security/pam_appl.h> 51 52 #include "sac.h" 53 #include "tmextern.h" 54 55 extern char *lastname(); 56 57 /* 58 * account - create a utmpx record for service 59 * 60 */ 61 62 int 63 account(line) 64 char *line; 65 { 66 struct utmpx utmpx; /* prototype utmpx entry */ 67 struct utmpx *up = &utmpx; /* and a pointer to it */ 68 69 (void) memset(up, '\0', sizeof (utmpx)); 70 up->ut_user[0] = '.'; 71 (void) strncpy(&up->ut_user[1], Tag, sizeof (up->ut_user)-1); 72 (void) strncpy(up->ut_line, lastname(line), sizeof (up->ut_line)); 73 up->ut_pid = getpid(); 74 up->ut_type = USER_PROCESS; 75 up->ut_id[0] = 't'; 76 up->ut_id[1] = 'm'; 77 up->ut_id[2] = SC_WILDC; 78 up->ut_id[3] = SC_WILDC; 79 up->ut_exit.e_termination = 0; 80 up->ut_exit.e_exit = 0; 81 (void) time(&up->ut_tv.tv_sec); 82 if (makeutx(up) == NULL) { 83 log("makeutx for pid %d failed", up->ut_pid); 84 return (-1); 85 } 86 return (0); 87 } 88 89 /* 90 * checkut_line - check if a login is active on the requested device 91 */ 92 int 93 checkut_line(char *line) 94 { 95 struct utmpx *u; 96 char buf[33], ttyn[33]; 97 int rvalue = 0; 98 pid_t ownpid = getpid(); 99 100 (void) strncpy(buf, lastname(line), sizeof (u->ut_line)); 101 buf[sizeof (u->ut_line)] = '\0'; 102 103 setutxent(); 104 while ((u = getutxent()) != NULL) { 105 if (u->ut_pid == ownpid) { 106 if (u->ut_type == USER_PROCESS) { 107 strncpy(ttyn, u->ut_line, sizeof (u->ut_line)); 108 ttyn[sizeof (u->ut_line)] = '\0'; 109 if (strcmp(buf, ttyn) == 0) { 110 rvalue = 1; 111 break; 112 } 113 } 114 } 115 } 116 endutxent(); 117 118 return (rvalue); 119 } 120 121 122 void 123 cleanut(pid, status) 124 pid_t pid; 125 int status; 126 { 127 pam_handle_t *pamh; 128 struct utmpx *up; 129 struct utmpx ut; 130 char user[33], ttyn[33], rhost[258]; 131 132 setutxent(); 133 while (up = getutxent()) { 134 if (up->ut_pid == pid) { 135 if (up->ut_type == DEAD_PROCESS) { 136 /* Cleaned up elsewhere. */ 137 break; 138 } 139 140 strncpy(user, up->ut_user, sizeof (up->ut_user)); 141 user[sizeof (up->ut_user)] = '\0'; 142 strncpy(ttyn, up->ut_line, sizeof (up->ut_line)); 143 ttyn[sizeof (up->ut_line)] = '\0'; 144 strncpy(rhost, up->ut_host, sizeof (up->ut_host)); 145 rhost[sizeof (up->ut_host)] = '\0'; 146 147 if (pam_start("ttymon", user, NULL, &pamh) 148 == PAM_SUCCESS) { 149 (void) pam_set_item(pamh, PAM_TTY, ttyn); 150 (void) pam_set_item(pamh, PAM_RHOST, rhost); 151 (void) pam_close_session(pamh, 0); 152 (void) pam_end(pamh, PAM_SUCCESS); 153 } 154 155 156 up->ut_type = DEAD_PROCESS; 157 up->ut_exit.e_termination = WTERMSIG(status); 158 up->ut_exit.e_exit = WEXITSTATUS(status); 159 (void) time(&up->ut_tv.tv_sec); 160 161 if (modutx(up) == NULL) { 162 /* 163 * Since modutx failed we'll 164 * write out the new entry 165 * ourselves. 166 */ 167 (void) pututxline(up); 168 updwtmpx("wtmpx", up); 169 } 170 break; 171 } 172 } 173 endutxent(); 174 } 175 176 /* 177 * getty_account - This is a copy of old getty account routine. 178 * - This is only called if ttymon is invoked as getty. 179 * - It tries to find its own INIT_PROCESS entry in utmpx 180 * - and change it to LOGIN_PROCESS 181 */ 182 void 183 getty_account(line) 184 char *line; 185 { 186 pid_t ownpid; 187 struct utmpx *u; 188 189 ownpid = getpid(); 190 191 setutxent(); 192 while ((u = getutxent()) != NULL) { 193 194 if (u->ut_type == INIT_PROCESS && u->ut_pid == ownpid) { 195 (void) strncpy(u->ut_line, lastname(line), 196 sizeof (u->ut_line)); 197 (void) strncpy(u->ut_user, "LOGIN", 198 sizeof (u->ut_user)); 199 u->ut_type = LOGIN_PROCESS; 200 201 /* Write out the updated entry. */ 202 (void) pututxline(u); 203 break; 204 } 205 } 206 207 /* create wtmpx entry also */ 208 if (u != NULL) 209 updwtmpx("/etc/wtmpx", u); 210 211 endutxent(); 212 } 213