1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* from UCB 5.4 6/23/85 */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate /* 32*7c478bd9Sstevel@tonic-gate * 4.2BSD, 2.9BSD, or ATTSVR4 TCP/IP server for uucico 33*7c478bd9Sstevel@tonic-gate * uucico's TCP channel causes this server to be run at the remote end. 34*7c478bd9Sstevel@tonic-gate */ 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #include "uucp.h" 37*7c478bd9Sstevel@tonic-gate #include <netdb.h> 38*7c478bd9Sstevel@tonic-gate #ifdef BSD2_9 39*7c478bd9Sstevel@tonic-gate #include <sys/localopts.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 41*7c478bd9Sstevel@tonic-gate #endif BSD2_9 42*7c478bd9Sstevel@tonic-gate #include <signal.h> 43*7c478bd9Sstevel@tonic-gate #include <errno.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 45*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 47*7c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY 48*7c478bd9Sstevel@tonic-gate #include <sys/termio.h> 49*7c478bd9Sstevel@tonic-gate #else 50*7c478bd9Sstevel@tonic-gate #include <sys/ioctl.h> 51*7c478bd9Sstevel@tonic-gate #endif 52*7c478bd9Sstevel@tonic-gate #include <pwd.h> 53*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 54*7c478bd9Sstevel@tonic-gate #include <shadow.h> 55*7c478bd9Sstevel@tonic-gate #endif 56*7c478bd9Sstevel@tonic-gate #include <lastlog.h> 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate #include <security/pam_appl.h> 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate static int uucp_conv(); 61*7c478bd9Sstevel@tonic-gate struct pam_conv conv = {uucp_conv, NULL }; 62*7c478bd9Sstevel@tonic-gate pam_handle_t *pamh; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate #if !defined(BSD4_2) && !defined(BSD2_9) && !defined(ATTSVR4) 65*7c478bd9Sstevel@tonic-gate --- You must have either BSD4_2, BSD2_9, or ATTSVR4 defined for this to work 66*7c478bd9Sstevel@tonic-gate #endif !BSD4_2 && !BSD2_9 67*7c478bd9Sstevel@tonic-gate #if defined(BSD4_2) && defined(BSD2_9) 68*7c478bd9Sstevel@tonic-gate --- You may not have both BSD4_2 and BSD2_9 defined for this to work 69*7c478bd9Sstevel@tonic-gate #endif /* check for stupidity */ 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate char lastlog[] = "/var/adm/lastlog"; 72*7c478bd9Sstevel@tonic-gate struct passwd nouser = { "", "nope", -1, -1, "", "", "", "", "" }; 73*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 74*7c478bd9Sstevel@tonic-gate struct spwd noupass = { "", "nope" }; 75*7c478bd9Sstevel@tonic-gate #endif 76*7c478bd9Sstevel@tonic-gate struct sockaddr_in hisctladdr; 77*7c478bd9Sstevel@tonic-gate socklen_t hisaddrlen = (socklen_t)sizeof (hisctladdr); 78*7c478bd9Sstevel@tonic-gate struct sockaddr_in myctladdr; 79*7c478bd9Sstevel@tonic-gate int nolog; /* don't log in utmp or wtmp */ 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate char Username[64]; 82*7c478bd9Sstevel@tonic-gate char Loginname[64]; 83*7c478bd9Sstevel@tonic-gate char *nenv[] = { 84*7c478bd9Sstevel@tonic-gate Username, 85*7c478bd9Sstevel@tonic-gate Loginname, 86*7c478bd9Sstevel@tonic-gate NULL, 87*7c478bd9Sstevel@tonic-gate }; 88*7c478bd9Sstevel@tonic-gate extern char **environ; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate main(argc, argv) 91*7c478bd9Sstevel@tonic-gate int argc; 92*7c478bd9Sstevel@tonic-gate char **argv; 93*7c478bd9Sstevel@tonic-gate { 94*7c478bd9Sstevel@tonic-gate #ifndef BSDINETD 95*7c478bd9Sstevel@tonic-gate register int s, tcp_socket; 96*7c478bd9Sstevel@tonic-gate struct servent *sp; 97*7c478bd9Sstevel@tonic-gate #endif !BSDINETD 98*7c478bd9Sstevel@tonic-gate extern int errno; 99*7c478bd9Sstevel@tonic-gate int dologout(); 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate if (argc > 1 && strcmp(argv[1], "-n") == 0) 102*7c478bd9Sstevel@tonic-gate nolog = 1; 103*7c478bd9Sstevel@tonic-gate environ = nenv; 104*7c478bd9Sstevel@tonic-gate #ifdef BSDINETD 105*7c478bd9Sstevel@tonic-gate close(1); close(2); 106*7c478bd9Sstevel@tonic-gate dup(0); dup(0); 107*7c478bd9Sstevel@tonic-gate hisaddrlen = (socklen_t)sizeof (hisctladdr); 108*7c478bd9Sstevel@tonic-gate if (getpeername(0, (struct sockaddr *)&hisctladdr, &hisaddrlen) < 0) { 109*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: ", argv[0]); 110*7c478bd9Sstevel@tonic-gate perror("getpeername"); 111*7c478bd9Sstevel@tonic-gate _exit(1); 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate if (fork() == 0) 114*7c478bd9Sstevel@tonic-gate doit(&hisctladdr); 115*7c478bd9Sstevel@tonic-gate dologout(); 116*7c478bd9Sstevel@tonic-gate exit(1); 117*7c478bd9Sstevel@tonic-gate #else !BSDINETD 118*7c478bd9Sstevel@tonic-gate sp = getservbyname("uucp", "tcp"); 119*7c478bd9Sstevel@tonic-gate if (sp == NULL) { 120*7c478bd9Sstevel@tonic-gate perror("uucpd: getservbyname"); 121*7c478bd9Sstevel@tonic-gate exit(1); 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate if (fork()) 124*7c478bd9Sstevel@tonic-gate exit(0); 125*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 126*7c478bd9Sstevel@tonic-gate setsid(); 127*7c478bd9Sstevel@tonic-gate #else 128*7c478bd9Sstevel@tonic-gate if ((s = open("/dev/tty", 2)) >= 0) { 129*7c478bd9Sstevel@tonic-gate ioctl(s, TIOCNOTTY, (char *)0); 130*7c478bd9Sstevel@tonic-gate close(s); 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate #endif 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 135*7c478bd9Sstevel@tonic-gate memset((void *)&myctladdr, 0, sizeof (myctladdr)); 136*7c478bd9Sstevel@tonic-gate #else 137*7c478bd9Sstevel@tonic-gate bzero((char *)&myctladdr, sizeof (myctladdr)); 138*7c478bd9Sstevel@tonic-gate #endif 139*7c478bd9Sstevel@tonic-gate myctladdr.sin_family = AF_INET; 140*7c478bd9Sstevel@tonic-gate myctladdr.sin_port = sp->s_port; 141*7c478bd9Sstevel@tonic-gate #if defined(BSD4_2) || defined(ATTSVR4) 142*7c478bd9Sstevel@tonic-gate tcp_socket = socket(AF_INET, SOCK_STREAM, 0); 143*7c478bd9Sstevel@tonic-gate if (tcp_socket < 0) { 144*7c478bd9Sstevel@tonic-gate perror("uucpd: socket"); 145*7c478bd9Sstevel@tonic-gate exit(1); 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) { 148*7c478bd9Sstevel@tonic-gate perror("uucpd: bind"); 149*7c478bd9Sstevel@tonic-gate exit(1); 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate listen(tcp_socket, 3); /* at most 3 simultaneuos uucp connections */ 152*7c478bd9Sstevel@tonic-gate signal(SIGCHLD, dologout); 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate for (;;) { 155*7c478bd9Sstevel@tonic-gate s = accept(tcp_socket, &hisctladdr, &hisaddrlen); 156*7c478bd9Sstevel@tonic-gate if (s < 0) { 157*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 158*7c478bd9Sstevel@tonic-gate continue; 159*7c478bd9Sstevel@tonic-gate perror("uucpd: accept"); 160*7c478bd9Sstevel@tonic-gate exit(1); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate if (fork() == 0) { 163*7c478bd9Sstevel@tonic-gate close(0); close(1); close(2); 164*7c478bd9Sstevel@tonic-gate dup(s); dup(s); dup(s); 165*7c478bd9Sstevel@tonic-gate close(tcp_socket); close(s); 166*7c478bd9Sstevel@tonic-gate doit(&hisctladdr); 167*7c478bd9Sstevel@tonic-gate exit(1); 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate close(s); 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate #endif BSD4_2 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate #ifdef BSD2_9 174*7c478bd9Sstevel@tonic-gate for (;;) { 175*7c478bd9Sstevel@tonic-gate signal(SIGCHLD, dologout); 176*7c478bd9Sstevel@tonic-gate s = socket(SOCK_STREAM, 0, &myctladdr, 177*7c478bd9Sstevel@tonic-gate SO_ACCEPTCONN|SO_KEEPALIVE); 178*7c478bd9Sstevel@tonic-gate if (s < 0) { 179*7c478bd9Sstevel@tonic-gate perror("uucpd: socket"); 180*7c478bd9Sstevel@tonic-gate exit(1); 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate if (accept(s, &hisctladdr) < 0) { 183*7c478bd9Sstevel@tonic-gate if (errno == EINTR) { 184*7c478bd9Sstevel@tonic-gate close(s); 185*7c478bd9Sstevel@tonic-gate continue; 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate perror("uucpd: accept"); 188*7c478bd9Sstevel@tonic-gate exit(1); 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate if (fork() == 0) { 191*7c478bd9Sstevel@tonic-gate close(0); close(1); close(2); 192*7c478bd9Sstevel@tonic-gate dup(s); dup(s); dup(s); 193*7c478bd9Sstevel@tonic-gate close(s); 194*7c478bd9Sstevel@tonic-gate doit(&hisctladdr); 195*7c478bd9Sstevel@tonic-gate exit(1); 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate #endif BSD2_9 199*7c478bd9Sstevel@tonic-gate #endif !BSDINETD 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate doit(sinp) 205*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sinp; 206*7c478bd9Sstevel@tonic-gate { 207*7c478bd9Sstevel@tonic-gate char user[64], passwd[64]; 208*7c478bd9Sstevel@tonic-gate struct passwd *pw, *getpwnam(); 209*7c478bd9Sstevel@tonic-gate int error; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate alarm(60); 212*7c478bd9Sstevel@tonic-gate printf("login: "); fflush(stdout); 213*7c478bd9Sstevel@tonic-gate if (readline(user, sizeof (user)) < 0) { 214*7c478bd9Sstevel@tonic-gate fprintf(stderr, "user read\n"); 215*7c478bd9Sstevel@tonic-gate return; 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /* 219*7c478bd9Sstevel@tonic-gate * Call pam_start to initiate a PAM authentication operation 220*7c478bd9Sstevel@tonic-gate */ 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate if ((pam_start("uucp", user, &conv, &pamh)) != PAM_SUCCESS) 223*7c478bd9Sstevel@tonic-gate return; 224*7c478bd9Sstevel@tonic-gate if ((pam_set_item(pamh, PAM_TTY, ttyname(0))) != PAM_SUCCESS) 225*7c478bd9Sstevel@tonic-gate return; 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate if (pam_authenticate(pamh, PAM_SILENT) != PAM_SUCCESS) { 228*7c478bd9Sstevel@tonic-gate /* force a delay if passwd bad */ 229*7c478bd9Sstevel@tonic-gate sleep(4); 230*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 231*7c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_ABORT); 232*7c478bd9Sstevel@tonic-gate return; 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate if ((error = pam_acct_mgmt(pamh, PAM_SILENT)) != PAM_SUCCESS) { 236*7c478bd9Sstevel@tonic-gate switch (error) { 237*7c478bd9Sstevel@tonic-gate case PAM_NEW_AUTHTOK_REQD: 238*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Password Expired."); 239*7c478bd9Sstevel@tonic-gate break; 240*7c478bd9Sstevel@tonic-gate case PAM_PERM_DENIED: 241*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Account Expired."); 242*7c478bd9Sstevel@tonic-gate break; 243*7c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_EXPIRED: 244*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Password Expired."); 245*7c478bd9Sstevel@tonic-gate break; 246*7c478bd9Sstevel@tonic-gate default: 247*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 248*7c478bd9Sstevel@tonic-gate break; 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_ABORT); 251*7c478bd9Sstevel@tonic-gate return; 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate if ((pw = getpwnam(user)) == NULL || strcmp(pw->pw_shell, UUCICO)) { 255*7c478bd9Sstevel@tonic-gate /* force a delay if user bad */ 256*7c478bd9Sstevel@tonic-gate sleep(4); 257*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 258*7c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_USER_UNKNOWN); 259*7c478bd9Sstevel@tonic-gate return; 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate alarm(0); 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate sprintf(Username, "USER=%s", user); 265*7c478bd9Sstevel@tonic-gate sprintf(Loginname, "LOGNAME=%s", user); 266*7c478bd9Sstevel@tonic-gate if (!nolog) 267*7c478bd9Sstevel@tonic-gate if (dologin(pw, sinp)) { 268*7c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_ABORT); 269*7c478bd9Sstevel@tonic-gate _exit(1); 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate /* set the real (and effective) GID */ 273*7c478bd9Sstevel@tonic-gate if (setgid(pw->pw_gid) == -1) { 274*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 275*7c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_PERM_DENIED); 276*7c478bd9Sstevel@tonic-gate return; 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate /* 280*7c478bd9Sstevel@tonic-gate * Initialize the supplementary group access list. 281*7c478bd9Sstevel@tonic-gate */ 282*7c478bd9Sstevel@tonic-gate if (initgroups(user, pw->pw_gid) == -1) { 283*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 284*7c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_PERM_DENIED); 285*7c478bd9Sstevel@tonic-gate return; 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate if (pam_setcred(pamh, PAM_ESTABLISH_CRED) != PAM_SUCCESS) { 289*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 290*7c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_CRED_INSUFFICIENT); 291*7c478bd9Sstevel@tonic-gate return; 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate /* set the real (and effective) UID */ 295*7c478bd9Sstevel@tonic-gate if (setuid(pw->pw_uid) == -1) { 296*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Login incorrect."); 297*7c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_CRED_ERR); 298*7c478bd9Sstevel@tonic-gate return; 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate chdir(pw->pw_dir); 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_SUCCESS); 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate #if defined(BSD4_2) || defined(ATTSVR4) 306*7c478bd9Sstevel@tonic-gate execl(UUCICO, "uucico", "-u", user, (char *)0); 307*7c478bd9Sstevel@tonic-gate #endif BSD4_2 308*7c478bd9Sstevel@tonic-gate #ifdef BSD2_9 309*7c478bd9Sstevel@tonic-gate sprintf(passwd, "-h%s", inet_ntoa(sinp->sin_addr)); 310*7c478bd9Sstevel@tonic-gate execl(UUCICO, "uucico", passwd, (char *)0); 311*7c478bd9Sstevel@tonic-gate #endif BSD2_9 312*7c478bd9Sstevel@tonic-gate perror("uucico server: execl"); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate readline(p, n) 316*7c478bd9Sstevel@tonic-gate register char *p; 317*7c478bd9Sstevel@tonic-gate register int n; 318*7c478bd9Sstevel@tonic-gate { 319*7c478bd9Sstevel@tonic-gate char c; 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate while (n-- > 0) { 322*7c478bd9Sstevel@tonic-gate if (read(0, &c, 1) <= 0) 323*7c478bd9Sstevel@tonic-gate return (-1); 324*7c478bd9Sstevel@tonic-gate c &= 0177; 325*7c478bd9Sstevel@tonic-gate if (c == '\n' || c == '\r') { 326*7c478bd9Sstevel@tonic-gate *p = '\0'; 327*7c478bd9Sstevel@tonic-gate return (0); 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate *p++ = c; 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate return (-1); 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 335*7c478bd9Sstevel@tonic-gate #include <sac.h> /* for SC_WILDC */ 336*7c478bd9Sstevel@tonic-gate #include <utmpx.h> 337*7c478bd9Sstevel@tonic-gate #else !ATTSVR4 338*7c478bd9Sstevel@tonic-gate #include <utmp.h> 339*7c478bd9Sstevel@tonic-gate #endif !ATTSVR4 340*7c478bd9Sstevel@tonic-gate #if defined(BSD4_2) || defined(ATTSVR4) 341*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 342*7c478bd9Sstevel@tonic-gate #endif BSD4_2 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate #ifdef BSD2_9 345*7c478bd9Sstevel@tonic-gate #define O_APPEND 0 /* kludge */ 346*7c478bd9Sstevel@tonic-gate #define wait3(a, b, c) wait2(a, b) 347*7c478bd9Sstevel@tonic-gate #endif BSD2_9 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate #define SCPYN(a, b) strncpy(a, b, sizeof (a)) 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 352*7c478bd9Sstevel@tonic-gate struct utmpx utmp; 353*7c478bd9Sstevel@tonic-gate #else !ATTSVR4 354*7c478bd9Sstevel@tonic-gate struct utmp utmp; 355*7c478bd9Sstevel@tonic-gate #endif !ATTSVR4 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate dologout() 358*7c478bd9Sstevel@tonic-gate { 359*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 360*7c478bd9Sstevel@tonic-gate int status; 361*7c478bd9Sstevel@tonic-gate #else !ATTSVR4 362*7c478bd9Sstevel@tonic-gate union wait status; 363*7c478bd9Sstevel@tonic-gate #endif !ATSVR4 364*7c478bd9Sstevel@tonic-gate int pid, wtmp; 365*7c478bd9Sstevel@tonic-gate /* the following 2 variables are needed for utmp mgmt */ 366*7c478bd9Sstevel@tonic-gate struct utmpx ut; 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate #ifdef BSDINETD 369*7c478bd9Sstevel@tonic-gate while ((pid = wait(&status)) > 0) { 370*7c478bd9Sstevel@tonic-gate #else !BSDINETD 371*7c478bd9Sstevel@tonic-gate while ((pid = wait3(&status, WNOHANG, 0)) > 0) { 372*7c478bd9Sstevel@tonic-gate #endif !BSDINETD 373*7c478bd9Sstevel@tonic-gate if (nolog) 374*7c478bd9Sstevel@tonic-gate continue; 375*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 376*7c478bd9Sstevel@tonic-gate /* clear out any residue from utmpx buffer */ 377*7c478bd9Sstevel@tonic-gate (void) memset((char *)&ut, 0, sizeof (ut)); 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate SCPYN(utmp.ut_user, ""); 380*7c478bd9Sstevel@tonic-gate ut.ut_id[0] = 'u'; 381*7c478bd9Sstevel@tonic-gate ut.ut_id[1] = 'u'; 382*7c478bd9Sstevel@tonic-gate ut.ut_id[2] = SC_WILDC; 383*7c478bd9Sstevel@tonic-gate ut.ut_id[3] = SC_WILDC; 384*7c478bd9Sstevel@tonic-gate sprintf(ut.ut_line, "uucp%.4d", pid); 385*7c478bd9Sstevel@tonic-gate ut.ut_pid = getpid(); 386*7c478bd9Sstevel@tonic-gate ut.ut_type = DEAD_PROCESS; 387*7c478bd9Sstevel@tonic-gate ut.ut_exit.e_termination = status & 0xFF; 388*7c478bd9Sstevel@tonic-gate ut.ut_exit.e_exit = WEXITSTATUS(status); 389*7c478bd9Sstevel@tonic-gate SCPYN(ut.ut_host, ""); 390*7c478bd9Sstevel@tonic-gate ut.ut_syslen = 1; 391*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&ut.ut_tv, NULL); 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate /* 394*7c478bd9Sstevel@tonic-gate * XXX: UUCPD does not do any pam session management. 395*7c478bd9Sstevel@tonic-gate * There is no way for the parent process to close 396*7c478bd9Sstevel@tonic-gate * the pam session after a child has exited. 397*7c478bd9Sstevel@tonic-gate */ 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate updwtmpx(WTMPX_FILE, &ut); 400*7c478bd9Sstevel@tonic-gate #else !ATTSVR4 401*7c478bd9Sstevel@tonic-gate wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); 402*7c478bd9Sstevel@tonic-gate if (wtmp >= 0) { 403*7c478bd9Sstevel@tonic-gate sprintf(utmp.ut_line, "uucp%.4d", pid); 404*7c478bd9Sstevel@tonic-gate SCPYN(utmp.ut_name, ""); 405*7c478bd9Sstevel@tonic-gate SCPYN(utmp.ut_host, ""); 406*7c478bd9Sstevel@tonic-gate (void) time(&utmp.ut_time); 407*7c478bd9Sstevel@tonic-gate #ifdef BSD2_9 408*7c478bd9Sstevel@tonic-gate (void) lseek(wtmp, 0L, 2); 409*7c478bd9Sstevel@tonic-gate #endif BSD2_9 410*7c478bd9Sstevel@tonic-gate (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 411*7c478bd9Sstevel@tonic-gate (void) close(wtmp); 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate #endif !ATTSVR4 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate /* 418*7c478bd9Sstevel@tonic-gate * Record login in wtmp file. 419*7c478bd9Sstevel@tonic-gate */ 420*7c478bd9Sstevel@tonic-gate dologin(pw, sin) 421*7c478bd9Sstevel@tonic-gate struct passwd *pw; 422*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 423*7c478bd9Sstevel@tonic-gate { 424*7c478bd9Sstevel@tonic-gate char line[32]; 425*7c478bd9Sstevel@tonic-gate char remotehost[32]; 426*7c478bd9Sstevel@tonic-gate int wtmp; 427*7c478bd9Sstevel@tonic-gate struct hostent *hp = gethostbyaddr((const char *)&sin->sin_addr, 428*7c478bd9Sstevel@tonic-gate sizeof (struct in_addr), AF_INET); 429*7c478bd9Sstevel@tonic-gate struct utmpx ut; 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate if (hp) { 432*7c478bd9Sstevel@tonic-gate strncpy(remotehost, hp->h_name, sizeof (remotehost)); 433*7c478bd9Sstevel@tonic-gate endhostent(); 434*7c478bd9Sstevel@tonic-gate } else 435*7c478bd9Sstevel@tonic-gate strncpy(remotehost, (char *)inet_ntoa(sin->sin_addr), 436*7c478bd9Sstevel@tonic-gate sizeof (remotehost)); 437*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4 438*7c478bd9Sstevel@tonic-gate /* clear wtmpx entry */ 439*7c478bd9Sstevel@tonic-gate (void) memset((void *)&ut, 0, sizeof (ut)); 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate SCPYN(ut.ut_user, pw->pw_name); 442*7c478bd9Sstevel@tonic-gate ut.ut_id[0] = 'u'; 443*7c478bd9Sstevel@tonic-gate ut.ut_id[1] = 'u'; 444*7c478bd9Sstevel@tonic-gate ut.ut_id[2] = SC_WILDC; 445*7c478bd9Sstevel@tonic-gate ut.ut_id[3] = SC_WILDC; 446*7c478bd9Sstevel@tonic-gate /* hack, but must be unique and no tty line */ 447*7c478bd9Sstevel@tonic-gate sprintf(line, "uucp%.4d", getpid()); 448*7c478bd9Sstevel@tonic-gate SCPYN(ut.ut_line, line); 449*7c478bd9Sstevel@tonic-gate ut.ut_pid = getpid(); 450*7c478bd9Sstevel@tonic-gate ut.ut_type = USER_PROCESS; 451*7c478bd9Sstevel@tonic-gate ut.ut_exit.e_termination = 0; 452*7c478bd9Sstevel@tonic-gate ut.ut_exit.e_exit = 0; 453*7c478bd9Sstevel@tonic-gate SCPYN(ut.ut_host, remotehost); 454*7c478bd9Sstevel@tonic-gate ut.ut_syslen = strlen(remotehost) + 1; 455*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&ut.ut_tv, 0); 456*7c478bd9Sstevel@tonic-gate updwtmpx(WTMPX_FILE, &ut); 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate /* 459*7c478bd9Sstevel@tonic-gate * XXX: 460*7c478bd9Sstevel@tonic-gate * We no longer do session management in uucpd because 461*7c478bd9Sstevel@tonic-gate * there is no way to do the "pam_close_session()". 462*7c478bd9Sstevel@tonic-gate * 463*7c478bd9Sstevel@tonic-gate * Processes like "init" can do a pam_close_session() 464*7c478bd9Sstevel@tonic-gate * because they can use the utmp entry to retrive 465*7c478bd9Sstevel@tonic-gate * the proper username, ttyname, etc. -- 466*7c478bd9Sstevel@tonic-gate * uucpd only writes to the wtmp file. 467*7c478bd9Sstevel@tonic-gate * 468*7c478bd9Sstevel@tonic-gate * ftpd (which also only writes to the wtmp file) 469*7c478bd9Sstevel@tonic-gate * can do a pam_close_session() because it doesn't fork(). 470*7c478bd9Sstevel@tonic-gate * 471*7c478bd9Sstevel@tonic-gate * if (pam_set_item(pamh, PAM_RHOST, remotehost) != PAM_SUCCESS) 472*7c478bd9Sstevel@tonic-gate * return (1); 473*7c478bd9Sstevel@tonic-gate * if (pam_set_item(pamh, PAM_TTY, line) != PAM_SUCCESS) 474*7c478bd9Sstevel@tonic-gate * return (1); 475*7c478bd9Sstevel@tonic-gate * if (pam_open_session(pamh, 0) != PAM_SUCCESS) { 476*7c478bd9Sstevel@tonic-gate * return (1); 477*7c478bd9Sstevel@tonic-gate * } 478*7c478bd9Sstevel@tonic-gate */ 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate #else !ATTSVR4 481*7c478bd9Sstevel@tonic-gate wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); 482*7c478bd9Sstevel@tonic-gate if (wtmp >= 0) { 483*7c478bd9Sstevel@tonic-gate /* hack, but must be unique and no tty line */ 484*7c478bd9Sstevel@tonic-gate sprintf(line, "uucp%.4d", getpid()); 485*7c478bd9Sstevel@tonic-gate SCPYN(utmp.ut_line, line); 486*7c478bd9Sstevel@tonic-gate SCPYN(utmp.ut_name, pw->pw_name); 487*7c478bd9Sstevel@tonic-gate SCPYN(utmp.ut_host, remotehost); 488*7c478bd9Sstevel@tonic-gate time(&utmp.ut_time); 489*7c478bd9Sstevel@tonic-gate #ifdef BSD2_9 490*7c478bd9Sstevel@tonic-gate (void) lseek(wtmp, 0L, 2); 491*7c478bd9Sstevel@tonic-gate #endif BSD2_9 492*7c478bd9Sstevel@tonic-gate (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 493*7c478bd9Sstevel@tonic-gate (void) close(wtmp); 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate #endif !ATTSVR4 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate return (0); 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate /* 501*7c478bd9Sstevel@tonic-gate * uucp_conv - This is the conv (conversation) function called from 502*7c478bd9Sstevel@tonic-gate * a PAM authentication module to print error messages 503*7c478bd9Sstevel@tonic-gate * or garner information from the user. 504*7c478bd9Sstevel@tonic-gate */ 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate static int 507*7c478bd9Sstevel@tonic-gate uucp_conv(num_msg, msg, response, appdata_ptr) 508*7c478bd9Sstevel@tonic-gate int num_msg; 509*7c478bd9Sstevel@tonic-gate struct pam_message **msg; 510*7c478bd9Sstevel@tonic-gate struct pam_response **response; 511*7c478bd9Sstevel@tonic-gate void *appdata_ptr; 512*7c478bd9Sstevel@tonic-gate { 513*7c478bd9Sstevel@tonic-gate struct pam_message *m; 514*7c478bd9Sstevel@tonic-gate struct pam_response *r; 515*7c478bd9Sstevel@tonic-gate char *temp; 516*7c478bd9Sstevel@tonic-gate static char passwd[64]; 517*7c478bd9Sstevel@tonic-gate int k, i; 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate if (num_msg <= 0) 520*7c478bd9Sstevel@tonic-gate return (PAM_CONV_ERR); 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate *response = (struct pam_response *)calloc(num_msg, 523*7c478bd9Sstevel@tonic-gate sizeof (struct pam_response)); 524*7c478bd9Sstevel@tonic-gate if (*response == NULL) 525*7c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate k = num_msg; 528*7c478bd9Sstevel@tonic-gate m = *msg; 529*7c478bd9Sstevel@tonic-gate r = *response; 530*7c478bd9Sstevel@tonic-gate while (k--) { 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate switch (m->msg_style) { 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_OFF: 535*7c478bd9Sstevel@tonic-gate /* 536*7c478bd9Sstevel@tonic-gate * we do this instead of using passed in message 537*7c478bd9Sstevel@tonic-gate * to prevent possible breakage of uucp protocol. 538*7c478bd9Sstevel@tonic-gate */ 539*7c478bd9Sstevel@tonic-gate printf("Password: "); fflush(stdout); 540*7c478bd9Sstevel@tonic-gate if (readline(passwd, sizeof (passwd)) < 0) { 541*7c478bd9Sstevel@tonic-gate fprintf(stderr, "passwd read\n"); 542*7c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate temp = passwd; 545*7c478bd9Sstevel@tonic-gate if (temp != NULL) { 546*7c478bd9Sstevel@tonic-gate r->resp = strdup(temp); 547*7c478bd9Sstevel@tonic-gate if (r->resp == NULL) { 548*7c478bd9Sstevel@tonic-gate /* free responses */ 549*7c478bd9Sstevel@tonic-gate r = *response; 550*7c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) { 551*7c478bd9Sstevel@tonic-gate if (r->resp) 552*7c478bd9Sstevel@tonic-gate free(r->resp); 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate free(*response); 555*7c478bd9Sstevel@tonic-gate *response = NULL; 556*7c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate } 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate m++; 561*7c478bd9Sstevel@tonic-gate r++; 562*7c478bd9Sstevel@tonic-gate break; 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_ON: 565*7c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 566*7c478bd9Sstevel@tonic-gate fputs(m->msg, stdout); 567*7c478bd9Sstevel@tonic-gate fflush(stdout); 568*7c478bd9Sstevel@tonic-gate } 569*7c478bd9Sstevel@tonic-gate r->resp = (char *)malloc(PAM_MAX_RESP_SIZE); 570*7c478bd9Sstevel@tonic-gate if (r->resp == NULL) { 571*7c478bd9Sstevel@tonic-gate /* free the response */ 572*7c478bd9Sstevel@tonic-gate r = *response; 573*7c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) { 574*7c478bd9Sstevel@tonic-gate if (r->resp) 575*7c478bd9Sstevel@tonic-gate free(r->resp); 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate free(*response); 578*7c478bd9Sstevel@tonic-gate *response = NULL; 579*7c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 580*7c478bd9Sstevel@tonic-gate } 581*7c478bd9Sstevel@tonic-gate (void) fgets(r->resp, PAM_MAX_RESP_SIZE, stdin); 582*7c478bd9Sstevel@tonic-gate m++; 583*7c478bd9Sstevel@tonic-gate r++; 584*7c478bd9Sstevel@tonic-gate break; 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate case PAM_ERROR_MSG: 587*7c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 588*7c478bd9Sstevel@tonic-gate fputs(m->msg, stderr); 589*7c478bd9Sstevel@tonic-gate fputs("\n", stderr); 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate m++; 592*7c478bd9Sstevel@tonic-gate r++; 593*7c478bd9Sstevel@tonic-gate break; 594*7c478bd9Sstevel@tonic-gate case PAM_TEXT_INFO: 595*7c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 596*7c478bd9Sstevel@tonic-gate fputs(m->msg, stdout); 597*7c478bd9Sstevel@tonic-gate fputs("\n", stdout); 598*7c478bd9Sstevel@tonic-gate } 599*7c478bd9Sstevel@tonic-gate m++; 600*7c478bd9Sstevel@tonic-gate r++; 601*7c478bd9Sstevel@tonic-gate break; 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate default: 604*7c478bd9Sstevel@tonic-gate break; 605*7c478bd9Sstevel@tonic-gate } 606*7c478bd9Sstevel@tonic-gate } 607*7c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 608*7c478bd9Sstevel@tonic-gate } 609