17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5f48205beScasper * Common Development and Distribution License (the "License"). 6f48205beScasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22f48205beScasper * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 26*2de0a7d6SDan McDonald #pragma ident "%Z%%M% %I% %E% SMI" 27*2de0a7d6SDan McDonald 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * 4.2BSD, 2.9BSD, or ATTSVR4 TCP/IP server for uucico 307c478bd9Sstevel@tonic-gate * uucico's TCP channel causes this server to be run at the remote end. 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include "uucp.h" 347c478bd9Sstevel@tonic-gate #include <netdb.h> 357c478bd9Sstevel@tonic-gate #ifdef BSD2_9 367c478bd9Sstevel@tonic-gate #include <sys/localopts.h> 377c478bd9Sstevel@tonic-gate #include <sys/file.h> 38462be471Sceastha #endif /* BSD2_9 */ 397c478bd9Sstevel@tonic-gate #include <signal.h> 407c478bd9Sstevel@tonic-gate #include <errno.h> 417c478bd9Sstevel@tonic-gate #include <sys/socket.h> 427c478bd9Sstevel@tonic-gate #include <netinet/in.h> 437c478bd9Sstevel@tonic-gate #include <sys/wait.h> 447c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY 457c478bd9Sstevel@tonic-gate #include <sys/termio.h> 467c478bd9Sstevel@tonic-gate #else 477c478bd9Sstevel@tonic-gate #include <sys/ioctl.h> 487c478bd9Sstevel@tonic-gate #endif 497c478bd9Sstevel@tonic-gate #include <pwd.h> 507c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 517c478bd9Sstevel@tonic-gate #include <shadow.h> 527c478bd9Sstevel@tonic-gate #endif 53*2de0a7d6SDan McDonald #include <lastlog.h> 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate #include <security/pam_appl.h> 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate static int uucp_conv(); 587c478bd9Sstevel@tonic-gate struct pam_conv conv = {uucp_conv, NULL }; 597c478bd9Sstevel@tonic-gate pam_handle_t *pamh; 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #if !defined(BSD4_2) && !defined(BSD2_9) && !defined(ATTSVR4) 627c478bd9Sstevel@tonic-gate --- You must have either BSD4_2, BSD2_9, or ATTSVR4 defined for this to work 63462be471Sceastha #endif /* !BSD4_2 && !BSD2_9 */ 647c478bd9Sstevel@tonic-gate #if defined(BSD4_2) && defined(BSD2_9) 657c478bd9Sstevel@tonic-gate --- You may not have both BSD4_2 and BSD2_9 defined for this to work 667c478bd9Sstevel@tonic-gate #endif /* check for stupidity */ 677c478bd9Sstevel@tonic-gate 68*2de0a7d6SDan McDonald char lastlog[] = "/var/adm/lastlog"; 69f48205beScasper struct passwd nouser = { 70f48205beScasper "", "nope", (uid_t)-1, (gid_t)-1, "", "", "", "", "" }; 717c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 727c478bd9Sstevel@tonic-gate struct spwd noupass = { "", "nope" }; 737c478bd9Sstevel@tonic-gate #endif 747c478bd9Sstevel@tonic-gate struct sockaddr_in hisctladdr; 757c478bd9Sstevel@tonic-gate socklen_t hisaddrlen = (socklen_t)sizeof (hisctladdr); 767c478bd9Sstevel@tonic-gate struct sockaddr_in myctladdr; 777c478bd9Sstevel@tonic-gate int nolog; /* don't log in utmp or wtmp */ 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate char Username[64]; 807c478bd9Sstevel@tonic-gate char Loginname[64]; 817c478bd9Sstevel@tonic-gate char *nenv[] = { 827c478bd9Sstevel@tonic-gate Username, 837c478bd9Sstevel@tonic-gate Loginname, 847c478bd9Sstevel@tonic-gate NULL, 857c478bd9Sstevel@tonic-gate }; 867c478bd9Sstevel@tonic-gate extern char **environ; 877c478bd9Sstevel@tonic-gate 88462be471Sceastha static void doit(struct sockaddr_in *); 89462be471Sceastha static void dologout(void); 90462be471Sceastha 91462be471Sceastha int 927c478bd9Sstevel@tonic-gate main(argc, argv) 937c478bd9Sstevel@tonic-gate int argc; 947c478bd9Sstevel@tonic-gate char **argv; 957c478bd9Sstevel@tonic-gate { 967c478bd9Sstevel@tonic-gate #ifndef BSDINETD 97462be471Sceastha int s, tcp_socket; 987c478bd9Sstevel@tonic-gate struct servent *sp; 99462be471Sceastha #endif /* !BSDINETD */ 1007c478bd9Sstevel@tonic-gate extern int errno; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate if (argc > 1 && strcmp(argv[1], "-n") == 0) 1037c478bd9Sstevel@tonic-gate nolog = 1; 1047c478bd9Sstevel@tonic-gate environ = nenv; 1057c478bd9Sstevel@tonic-gate #ifdef BSDINETD 1067c478bd9Sstevel@tonic-gate close(1); close(2); 1077c478bd9Sstevel@tonic-gate dup(0); dup(0); 1087c478bd9Sstevel@tonic-gate hisaddrlen = (socklen_t)sizeof (hisctladdr); 1097c478bd9Sstevel@tonic-gate if (getpeername(0, (struct sockaddr *)&hisctladdr, &hisaddrlen) < 0) { 1107c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: ", argv[0]); 1117c478bd9Sstevel@tonic-gate perror("getpeername"); 1127c478bd9Sstevel@tonic-gate _exit(1); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate if (fork() == 0) 1157c478bd9Sstevel@tonic-gate doit(&hisctladdr); 1167c478bd9Sstevel@tonic-gate dologout(); 1177c478bd9Sstevel@tonic-gate exit(1); 118462be471Sceastha #else /* !BSDINETD */ 1197c478bd9Sstevel@tonic-gate sp = getservbyname("uucp", "tcp"); 1207c478bd9Sstevel@tonic-gate if (sp == NULL) { 1217c478bd9Sstevel@tonic-gate perror("uucpd: getservbyname"); 1227c478bd9Sstevel@tonic-gate exit(1); 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate if (fork()) 1257c478bd9Sstevel@tonic-gate exit(0); 1267c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 1277c478bd9Sstevel@tonic-gate setsid(); 1287c478bd9Sstevel@tonic-gate #else 1297c478bd9Sstevel@tonic-gate if ((s = open("/dev/tty", 2)) >= 0) { 1307c478bd9Sstevel@tonic-gate ioctl(s, TIOCNOTTY, (char *)0); 1317c478bd9Sstevel@tonic-gate close(s); 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate #endif 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 1367c478bd9Sstevel@tonic-gate memset((void *)&myctladdr, 0, sizeof (myctladdr)); 1377c478bd9Sstevel@tonic-gate #else 1387c478bd9Sstevel@tonic-gate bzero((char *)&myctladdr, sizeof (myctladdr)); 1397c478bd9Sstevel@tonic-gate #endif 1407c478bd9Sstevel@tonic-gate myctladdr.sin_family = AF_INET; 1417c478bd9Sstevel@tonic-gate myctladdr.sin_port = sp->s_port; 1427c478bd9Sstevel@tonic-gate #if defined(BSD4_2) || defined(ATTSVR4) 1437c478bd9Sstevel@tonic-gate tcp_socket = socket(AF_INET, SOCK_STREAM, 0); 1447c478bd9Sstevel@tonic-gate if (tcp_socket < 0) { 1457c478bd9Sstevel@tonic-gate perror("uucpd: socket"); 1467c478bd9Sstevel@tonic-gate exit(1); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) { 1497c478bd9Sstevel@tonic-gate perror("uucpd: bind"); 1507c478bd9Sstevel@tonic-gate exit(1); 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate listen(tcp_socket, 3); /* at most 3 simultaneuos uucp connections */ 1537c478bd9Sstevel@tonic-gate signal(SIGCHLD, dologout); 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate for (;;) { 1567c478bd9Sstevel@tonic-gate s = accept(tcp_socket, &hisctladdr, &hisaddrlen); 1577c478bd9Sstevel@tonic-gate if (s < 0) { 1587c478bd9Sstevel@tonic-gate if (errno == EINTR) 1597c478bd9Sstevel@tonic-gate continue; 1607c478bd9Sstevel@tonic-gate perror("uucpd: accept"); 1617c478bd9Sstevel@tonic-gate exit(1); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate if (fork() == 0) { 1647c478bd9Sstevel@tonic-gate close(0); close(1); close(2); 1657c478bd9Sstevel@tonic-gate dup(s); dup(s); dup(s); 1667c478bd9Sstevel@tonic-gate close(tcp_socket); close(s); 1677c478bd9Sstevel@tonic-gate doit(&hisctladdr); 1687c478bd9Sstevel@tonic-gate exit(1); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate close(s); 1717c478bd9Sstevel@tonic-gate } 172462be471Sceastha #endif /* BSD4_2 */ 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate #ifdef BSD2_9 1757c478bd9Sstevel@tonic-gate for (;;) { 1767c478bd9Sstevel@tonic-gate signal(SIGCHLD, dologout); 1777c478bd9Sstevel@tonic-gate s = socket(SOCK_STREAM, 0, &myctladdr, 1787c478bd9Sstevel@tonic-gate SO_ACCEPTCONN|SO_KEEPALIVE); 1797c478bd9Sstevel@tonic-gate if (s < 0) { 1807c478bd9Sstevel@tonic-gate perror("uucpd: socket"); 1817c478bd9Sstevel@tonic-gate exit(1); 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate if (accept(s, &hisctladdr) < 0) { 1847c478bd9Sstevel@tonic-gate if (errno == EINTR) { 1857c478bd9Sstevel@tonic-gate close(s); 1867c478bd9Sstevel@tonic-gate continue; 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate perror("uucpd: accept"); 1897c478bd9Sstevel@tonic-gate exit(1); 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate if (fork() == 0) { 1927c478bd9Sstevel@tonic-gate close(0); close(1); close(2); 1937c478bd9Sstevel@tonic-gate dup(s); dup(s); dup(s); 1947c478bd9Sstevel@tonic-gate close(s); 1957c478bd9Sstevel@tonic-gate doit(&hisctladdr); 1967c478bd9Sstevel@tonic-gate exit(1); 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate } 199462be471Sceastha #endif /* BSD2_9 */ 200462be471Sceastha #endif /* !BSDINETD */ 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 205462be471Sceastha static void 2067c478bd9Sstevel@tonic-gate doit(sinp) 2077c478bd9Sstevel@tonic-gate struct sockaddr_in *sinp; 2087c478bd9Sstevel@tonic-gate { 2097c478bd9Sstevel@tonic-gate char user[64], passwd[64]; 2107c478bd9Sstevel@tonic-gate struct passwd *pw, *getpwnam(); 2117c478bd9Sstevel@tonic-gate int error; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate alarm(60); 2147c478bd9Sstevel@tonic-gate printf("login: "); fflush(stdout); 2157c478bd9Sstevel@tonic-gate if (readline(user, sizeof (user)) < 0) { 2167c478bd9Sstevel@tonic-gate fprintf(stderr, "user read\n"); 2177c478bd9Sstevel@tonic-gate return; 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate /* 2217c478bd9Sstevel@tonic-gate * Call pam_start to initiate a PAM authentication operation 2227c478bd9Sstevel@tonic-gate */ 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate if ((pam_start("uucp", user, &conv, &pamh)) != PAM_SUCCESS) 2257c478bd9Sstevel@tonic-gate return; 2267c478bd9Sstevel@tonic-gate if ((pam_set_item(pamh, PAM_TTY, ttyname(0))) != PAM_SUCCESS) 2277c478bd9Sstevel@tonic-gate return; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate if (pam_authenticate(pamh, PAM_SILENT) != PAM_SUCCESS) { 2307c478bd9Sstevel@tonic-gate /* force a delay if passwd bad */ 2317c478bd9Sstevel@tonic-gate sleep(4); 2327c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 2337c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_ABORT); 2347c478bd9Sstevel@tonic-gate return; 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate if ((error = pam_acct_mgmt(pamh, PAM_SILENT)) != PAM_SUCCESS) { 2387c478bd9Sstevel@tonic-gate switch (error) { 2397c478bd9Sstevel@tonic-gate case PAM_NEW_AUTHTOK_REQD: 2407c478bd9Sstevel@tonic-gate fprintf(stderr, "Password Expired."); 2417c478bd9Sstevel@tonic-gate break; 2427c478bd9Sstevel@tonic-gate case PAM_PERM_DENIED: 2437c478bd9Sstevel@tonic-gate fprintf(stderr, "Account Expired."); 2447c478bd9Sstevel@tonic-gate break; 2457c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_EXPIRED: 2467c478bd9Sstevel@tonic-gate fprintf(stderr, "Password Expired."); 2477c478bd9Sstevel@tonic-gate break; 2487c478bd9Sstevel@tonic-gate default: 2497c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 2507c478bd9Sstevel@tonic-gate break; 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_ABORT); 2537c478bd9Sstevel@tonic-gate return; 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate if ((pw = getpwnam(user)) == NULL || strcmp(pw->pw_shell, UUCICO)) { 2577c478bd9Sstevel@tonic-gate /* force a delay if user bad */ 2587c478bd9Sstevel@tonic-gate sleep(4); 2597c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 2607c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_USER_UNKNOWN); 2617c478bd9Sstevel@tonic-gate return; 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate alarm(0); 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate sprintf(Username, "USER=%s", user); 2677c478bd9Sstevel@tonic-gate sprintf(Loginname, "LOGNAME=%s", user); 2687c478bd9Sstevel@tonic-gate if (!nolog) 2697c478bd9Sstevel@tonic-gate if (dologin(pw, sinp)) { 2707c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_ABORT); 2717c478bd9Sstevel@tonic-gate _exit(1); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate /* set the real (and effective) GID */ 2757c478bd9Sstevel@tonic-gate if (setgid(pw->pw_gid) == -1) { 2767c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 2777c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_PERM_DENIED); 2787c478bd9Sstevel@tonic-gate return; 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* 2827c478bd9Sstevel@tonic-gate * Initialize the supplementary group access list. 2837c478bd9Sstevel@tonic-gate */ 2847c478bd9Sstevel@tonic-gate if (initgroups(user, pw->pw_gid) == -1) { 2857c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 2867c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_PERM_DENIED); 2877c478bd9Sstevel@tonic-gate return; 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate if (pam_setcred(pamh, PAM_ESTABLISH_CRED) != PAM_SUCCESS) { 2917c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 2927c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_CRED_INSUFFICIENT); 2937c478bd9Sstevel@tonic-gate return; 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate /* set the real (and effective) UID */ 2977c478bd9Sstevel@tonic-gate if (setuid(pw->pw_uid) == -1) { 2987c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 2997c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_CRED_ERR); 3007c478bd9Sstevel@tonic-gate return; 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate chdir(pw->pw_dir); 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_SUCCESS); 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate #if defined(BSD4_2) || defined(ATTSVR4) 3087c478bd9Sstevel@tonic-gate execl(UUCICO, "uucico", "-u", user, (char *)0); 309462be471Sceastha #endif /* BSD4_2 */ 3107c478bd9Sstevel@tonic-gate #ifdef BSD2_9 3117c478bd9Sstevel@tonic-gate sprintf(passwd, "-h%s", inet_ntoa(sinp->sin_addr)); 3127c478bd9Sstevel@tonic-gate execl(UUCICO, "uucico", passwd, (char *)0); 313462be471Sceastha #endif /* BSD2_9 */ 3147c478bd9Sstevel@tonic-gate perror("uucico server: execl"); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 317462be471Sceastha int 3187c478bd9Sstevel@tonic-gate readline(p, n) 319462be471Sceastha char *p; 320462be471Sceastha int n; 3217c478bd9Sstevel@tonic-gate { 3227c478bd9Sstevel@tonic-gate char c; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate while (n-- > 0) { 3257c478bd9Sstevel@tonic-gate if (read(0, &c, 1) <= 0) 3267c478bd9Sstevel@tonic-gate return (-1); 3277c478bd9Sstevel@tonic-gate c &= 0177; 3287c478bd9Sstevel@tonic-gate if (c == '\n' || c == '\r') { 3297c478bd9Sstevel@tonic-gate *p = '\0'; 3307c478bd9Sstevel@tonic-gate return (0); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate *p++ = c; 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate return (-1); 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 3387c478bd9Sstevel@tonic-gate #include <sac.h> /* for SC_WILDC */ 3397c478bd9Sstevel@tonic-gate #include <utmpx.h> 340462be471Sceastha #else /* !ATTSVR4 */ 3417c478bd9Sstevel@tonic-gate #include <utmp.h> 342462be471Sceastha #endif /* !ATTSVR4 */ 3437c478bd9Sstevel@tonic-gate #if defined(BSD4_2) || defined(ATTSVR4) 3447c478bd9Sstevel@tonic-gate #include <fcntl.h> 345462be471Sceastha #endif /* BSD4_2 */ 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate #ifdef BSD2_9 3487c478bd9Sstevel@tonic-gate #define O_APPEND 0 /* kludge */ 3497c478bd9Sstevel@tonic-gate #define wait3(a, b, c) wait2(a, b) 350462be471Sceastha #endif /* BSD2_9 */ 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate #define SCPYN(a, b) strncpy(a, b, sizeof (a)) 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 3557c478bd9Sstevel@tonic-gate struct utmpx utmp; 356462be471Sceastha #else /* !ATTSVR4 */ 3577c478bd9Sstevel@tonic-gate struct utmp utmp; 358462be471Sceastha #endif /* !ATTSVR4 */ 3597c478bd9Sstevel@tonic-gate 360462be471Sceastha static void 361462be471Sceastha dologout(void) 3627c478bd9Sstevel@tonic-gate { 3637c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 3647c478bd9Sstevel@tonic-gate int status; 365462be471Sceastha #else /* !ATTSVR4 */ 3667c478bd9Sstevel@tonic-gate union wait status; 367462be471Sceastha #endif /* !ATSVR4 */ 3687c478bd9Sstevel@tonic-gate int pid, wtmp; 3697c478bd9Sstevel@tonic-gate /* the following 2 variables are needed for utmp mgmt */ 3707c478bd9Sstevel@tonic-gate struct utmpx ut; 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate #ifdef BSDINETD 3737c478bd9Sstevel@tonic-gate while ((pid = wait(&status)) > 0) { 374462be471Sceastha #else /* !BSDINETD */ 3757c478bd9Sstevel@tonic-gate while ((pid = wait3(&status, WNOHANG, 0)) > 0) { 376462be471Sceastha #endif /* !BSDINETD */ 3777c478bd9Sstevel@tonic-gate if (nolog) 3787c478bd9Sstevel@tonic-gate continue; 3797c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 3807c478bd9Sstevel@tonic-gate /* clear out any residue from utmpx buffer */ 3817c478bd9Sstevel@tonic-gate (void) memset((char *)&ut, 0, sizeof (ut)); 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate SCPYN(utmp.ut_user, ""); 3847c478bd9Sstevel@tonic-gate ut.ut_id[0] = 'u'; 3857c478bd9Sstevel@tonic-gate ut.ut_id[1] = 'u'; 3867c478bd9Sstevel@tonic-gate ut.ut_id[2] = SC_WILDC; 3877c478bd9Sstevel@tonic-gate ut.ut_id[3] = SC_WILDC; 3887c478bd9Sstevel@tonic-gate sprintf(ut.ut_line, "uucp%.4d", pid); 3897c478bd9Sstevel@tonic-gate ut.ut_pid = getpid(); 3907c478bd9Sstevel@tonic-gate ut.ut_type = DEAD_PROCESS; 3917c478bd9Sstevel@tonic-gate ut.ut_exit.e_termination = status & 0xFF; 3927c478bd9Sstevel@tonic-gate ut.ut_exit.e_exit = WEXITSTATUS(status); 3937c478bd9Sstevel@tonic-gate SCPYN(ut.ut_host, ""); 3947c478bd9Sstevel@tonic-gate ut.ut_syslen = 1; 3957c478bd9Sstevel@tonic-gate (void) gettimeofday(&ut.ut_tv, NULL); 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate /* 3987c478bd9Sstevel@tonic-gate * XXX: UUCPD does not do any pam session management. 3997c478bd9Sstevel@tonic-gate * There is no way for the parent process to close 4007c478bd9Sstevel@tonic-gate * the pam session after a child has exited. 4017c478bd9Sstevel@tonic-gate */ 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate updwtmpx(WTMPX_FILE, &ut); 404462be471Sceastha #else /* !ATTSVR4 */ 4057c478bd9Sstevel@tonic-gate wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); 4067c478bd9Sstevel@tonic-gate if (wtmp >= 0) { 4077c478bd9Sstevel@tonic-gate sprintf(utmp.ut_line, "uucp%.4d", pid); 4087c478bd9Sstevel@tonic-gate SCPYN(utmp.ut_name, ""); 4097c478bd9Sstevel@tonic-gate SCPYN(utmp.ut_host, ""); 4107c478bd9Sstevel@tonic-gate (void) time(&utmp.ut_time); 4117c478bd9Sstevel@tonic-gate #ifdef BSD2_9 4127c478bd9Sstevel@tonic-gate (void) lseek(wtmp, 0L, 2); 413462be471Sceastha #endif /* BSD2_9 */ 4147c478bd9Sstevel@tonic-gate (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 4157c478bd9Sstevel@tonic-gate (void) close(wtmp); 4167c478bd9Sstevel@tonic-gate } 417462be471Sceastha #endif /* !ATTSVR4 */ 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* 4227c478bd9Sstevel@tonic-gate * Record login in wtmp file. 4237c478bd9Sstevel@tonic-gate */ 424462be471Sceastha int 4257c478bd9Sstevel@tonic-gate dologin(pw, sin) 4267c478bd9Sstevel@tonic-gate struct passwd *pw; 4277c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 4287c478bd9Sstevel@tonic-gate { 4297c478bd9Sstevel@tonic-gate char line[32]; 4307c478bd9Sstevel@tonic-gate char remotehost[32]; 4317c478bd9Sstevel@tonic-gate int wtmp; 4327c478bd9Sstevel@tonic-gate struct hostent *hp = gethostbyaddr((const char *)&sin->sin_addr, 4337c478bd9Sstevel@tonic-gate sizeof (struct in_addr), AF_INET); 4347c478bd9Sstevel@tonic-gate struct utmpx ut; 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate if (hp) { 4377c478bd9Sstevel@tonic-gate strncpy(remotehost, hp->h_name, sizeof (remotehost)); 4387c478bd9Sstevel@tonic-gate endhostent(); 4397c478bd9Sstevel@tonic-gate } else 4407c478bd9Sstevel@tonic-gate strncpy(remotehost, (char *)inet_ntoa(sin->sin_addr), 4417c478bd9Sstevel@tonic-gate sizeof (remotehost)); 4427c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 4437c478bd9Sstevel@tonic-gate /* clear wtmpx entry */ 4447c478bd9Sstevel@tonic-gate (void) memset((void *)&ut, 0, sizeof (ut)); 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate SCPYN(ut.ut_user, pw->pw_name); 4477c478bd9Sstevel@tonic-gate ut.ut_id[0] = 'u'; 4487c478bd9Sstevel@tonic-gate ut.ut_id[1] = 'u'; 4497c478bd9Sstevel@tonic-gate ut.ut_id[2] = SC_WILDC; 4507c478bd9Sstevel@tonic-gate ut.ut_id[3] = SC_WILDC; 4517c478bd9Sstevel@tonic-gate /* hack, but must be unique and no tty line */ 4527c478bd9Sstevel@tonic-gate sprintf(line, "uucp%.4d", getpid()); 4537c478bd9Sstevel@tonic-gate SCPYN(ut.ut_line, line); 4547c478bd9Sstevel@tonic-gate ut.ut_pid = getpid(); 4557c478bd9Sstevel@tonic-gate ut.ut_type = USER_PROCESS; 4567c478bd9Sstevel@tonic-gate ut.ut_exit.e_termination = 0; 4577c478bd9Sstevel@tonic-gate ut.ut_exit.e_exit = 0; 4587c478bd9Sstevel@tonic-gate SCPYN(ut.ut_host, remotehost); 4597c478bd9Sstevel@tonic-gate ut.ut_syslen = strlen(remotehost) + 1; 4607c478bd9Sstevel@tonic-gate (void) gettimeofday(&ut.ut_tv, 0); 4617c478bd9Sstevel@tonic-gate updwtmpx(WTMPX_FILE, &ut); 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate /* 4647c478bd9Sstevel@tonic-gate * XXX: 4657c478bd9Sstevel@tonic-gate * We no longer do session management in uucpd because 4667c478bd9Sstevel@tonic-gate * there is no way to do the "pam_close_session()". 4677c478bd9Sstevel@tonic-gate * 4687c478bd9Sstevel@tonic-gate * Processes like "init" can do a pam_close_session() 469da6c28aaSamw * because they can use the utmp entry to retrieve 4707c478bd9Sstevel@tonic-gate * the proper username, ttyname, etc. -- 4717c478bd9Sstevel@tonic-gate * uucpd only writes to the wtmp file. 4727c478bd9Sstevel@tonic-gate * 4737c478bd9Sstevel@tonic-gate * ftpd (which also only writes to the wtmp file) 4747c478bd9Sstevel@tonic-gate * can do a pam_close_session() because it doesn't fork(). 4757c478bd9Sstevel@tonic-gate * 4767c478bd9Sstevel@tonic-gate * if (pam_set_item(pamh, PAM_RHOST, remotehost) != PAM_SUCCESS) 4777c478bd9Sstevel@tonic-gate * return (1); 4787c478bd9Sstevel@tonic-gate * if (pam_set_item(pamh, PAM_TTY, line) != PAM_SUCCESS) 4797c478bd9Sstevel@tonic-gate * return (1); 4807c478bd9Sstevel@tonic-gate * if (pam_open_session(pamh, 0) != PAM_SUCCESS) { 4817c478bd9Sstevel@tonic-gate * return (1); 4827c478bd9Sstevel@tonic-gate * } 4837c478bd9Sstevel@tonic-gate */ 4847c478bd9Sstevel@tonic-gate 485462be471Sceastha #else /* !ATTSVR4 */ 4867c478bd9Sstevel@tonic-gate wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); 4877c478bd9Sstevel@tonic-gate if (wtmp >= 0) { 4887c478bd9Sstevel@tonic-gate /* hack, but must be unique and no tty line */ 4897c478bd9Sstevel@tonic-gate sprintf(line, "uucp%.4d", getpid()); 4907c478bd9Sstevel@tonic-gate SCPYN(utmp.ut_line, line); 4917c478bd9Sstevel@tonic-gate SCPYN(utmp.ut_name, pw->pw_name); 4927c478bd9Sstevel@tonic-gate SCPYN(utmp.ut_host, remotehost); 4937c478bd9Sstevel@tonic-gate time(&utmp.ut_time); 4947c478bd9Sstevel@tonic-gate #ifdef BSD2_9 4957c478bd9Sstevel@tonic-gate (void) lseek(wtmp, 0L, 2); 496462be471Sceastha #endif /* BSD2_9 */ 4977c478bd9Sstevel@tonic-gate (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 4987c478bd9Sstevel@tonic-gate (void) close(wtmp); 4997c478bd9Sstevel@tonic-gate } 500462be471Sceastha #endif /* !ATTSVR4 */ 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate return (0); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate /* 5067c478bd9Sstevel@tonic-gate * uucp_conv - This is the conv (conversation) function called from 5077c478bd9Sstevel@tonic-gate * a PAM authentication module to print error messages 5087c478bd9Sstevel@tonic-gate * or garner information from the user. 5097c478bd9Sstevel@tonic-gate */ 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate static int 5127c478bd9Sstevel@tonic-gate uucp_conv(num_msg, msg, response, appdata_ptr) 5137c478bd9Sstevel@tonic-gate int num_msg; 5147c478bd9Sstevel@tonic-gate struct pam_message **msg; 5157c478bd9Sstevel@tonic-gate struct pam_response **response; 5167c478bd9Sstevel@tonic-gate void *appdata_ptr; 5177c478bd9Sstevel@tonic-gate { 5187c478bd9Sstevel@tonic-gate struct pam_message *m; 5197c478bd9Sstevel@tonic-gate struct pam_response *r; 5207c478bd9Sstevel@tonic-gate char *temp; 5217c478bd9Sstevel@tonic-gate static char passwd[64]; 5227c478bd9Sstevel@tonic-gate int k, i; 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate if (num_msg <= 0) 5257c478bd9Sstevel@tonic-gate return (PAM_CONV_ERR); 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate *response = (struct pam_response *)calloc(num_msg, 5287c478bd9Sstevel@tonic-gate sizeof (struct pam_response)); 5297c478bd9Sstevel@tonic-gate if (*response == NULL) 5307c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate k = num_msg; 5337c478bd9Sstevel@tonic-gate m = *msg; 5347c478bd9Sstevel@tonic-gate r = *response; 5357c478bd9Sstevel@tonic-gate while (k--) { 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate switch (m->msg_style) { 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_OFF: 5407c478bd9Sstevel@tonic-gate /* 5417c478bd9Sstevel@tonic-gate * we do this instead of using passed in message 5427c478bd9Sstevel@tonic-gate * to prevent possible breakage of uucp protocol. 5437c478bd9Sstevel@tonic-gate */ 5447c478bd9Sstevel@tonic-gate printf("Password: "); fflush(stdout); 5457c478bd9Sstevel@tonic-gate if (readline(passwd, sizeof (passwd)) < 0) { 5467c478bd9Sstevel@tonic-gate fprintf(stderr, "passwd read\n"); 5477c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate temp = passwd; 5507c478bd9Sstevel@tonic-gate if (temp != NULL) { 5517c478bd9Sstevel@tonic-gate r->resp = strdup(temp); 5527c478bd9Sstevel@tonic-gate if (r->resp == NULL) { 5537c478bd9Sstevel@tonic-gate /* free responses */ 5547c478bd9Sstevel@tonic-gate r = *response; 5557c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) { 5567c478bd9Sstevel@tonic-gate if (r->resp) 5577c478bd9Sstevel@tonic-gate free(r->resp); 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate free(*response); 5607c478bd9Sstevel@tonic-gate *response = NULL; 5617c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate m++; 5667c478bd9Sstevel@tonic-gate r++; 5677c478bd9Sstevel@tonic-gate break; 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_ON: 5707c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 5717c478bd9Sstevel@tonic-gate fputs(m->msg, stdout); 5727c478bd9Sstevel@tonic-gate fflush(stdout); 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate r->resp = (char *)malloc(PAM_MAX_RESP_SIZE); 5757c478bd9Sstevel@tonic-gate if (r->resp == NULL) { 5767c478bd9Sstevel@tonic-gate /* free the response */ 5777c478bd9Sstevel@tonic-gate r = *response; 5787c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) { 5797c478bd9Sstevel@tonic-gate if (r->resp) 5807c478bd9Sstevel@tonic-gate free(r->resp); 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate free(*response); 5837c478bd9Sstevel@tonic-gate *response = NULL; 5847c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate (void) fgets(r->resp, PAM_MAX_RESP_SIZE, stdin); 5877c478bd9Sstevel@tonic-gate m++; 5887c478bd9Sstevel@tonic-gate r++; 5897c478bd9Sstevel@tonic-gate break; 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate case PAM_ERROR_MSG: 5927c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 5937c478bd9Sstevel@tonic-gate fputs(m->msg, stderr); 5947c478bd9Sstevel@tonic-gate fputs("\n", stderr); 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate m++; 5977c478bd9Sstevel@tonic-gate r++; 5987c478bd9Sstevel@tonic-gate break; 5997c478bd9Sstevel@tonic-gate case PAM_TEXT_INFO: 6007c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 6017c478bd9Sstevel@tonic-gate fputs(m->msg, stdout); 6027c478bd9Sstevel@tonic-gate fputs("\n", stdout); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate m++; 6057c478bd9Sstevel@tonic-gate r++; 6067c478bd9Sstevel@tonic-gate break; 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate default: 6097c478bd9Sstevel@tonic-gate break; 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 6137c478bd9Sstevel@tonic-gate } 614