/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* uucico's TCP channel causes this server to be run at the remote end.
*/
#include "uucp.h"
#include <netdb.h>
#ifdef BSD2_9
#include <sys/localopts.h>
#endif /* BSD2_9 */
#include <signal.h>
#include <errno.h>
#ifdef ATTSVTTY
#else
#endif
#include <pwd.h>
#ifdef ATTSVR4
#include <shadow.h>
#endif
#include <lastlog.h>
#include <security/pam_appl.h>
static int uucp_conv();
#endif /* !BSD4_2 && !BSD2_9 */
#endif /* check for stupidity */
#ifdef ATTSVR4
#endif
char *nenv[] = {
NULL,
};
extern char **environ;
static void doit(struct sockaddr_in *);
static void dologout(void);
int
int argc;
char **argv;
{
#ifndef BSDINETD
int s, tcp_socket;
#endif /* !BSDINETD */
extern int errno;
nolog = 1;
#ifdef BSDINETD
perror("getpeername");
_exit(1);
}
if (fork() == 0)
doit(&hisctladdr);
dologout();
exit(1);
#else /* !BSDINETD */
perror("uucpd: getservbyname");
exit(1);
}
if (fork())
exit(0);
#ifdef ATTSVR4
setsid();
#else
close(s);
}
#endif
#ifdef ATTSVR4
#else
#endif
if (tcp_socket < 0) {
perror("uucpd: socket");
exit(1);
}
perror("uucpd: bind");
exit(1);
}
for (;;) {
if (s < 0) {
continue;
perror("uucpd: accept");
exit(1);
}
if (fork() == 0) {
doit(&hisctladdr);
exit(1);
}
close(s);
}
#endif /* BSD4_2 */
#ifdef BSD2_9
for (;;) {
if (s < 0) {
perror("uucpd: socket");
exit(1);
}
if (accept(s, &hisctladdr) < 0) {
close(s);
continue;
}
perror("uucpd: accept");
exit(1);
}
if (fork() == 0) {
close(s);
doit(&hisctladdr);
exit(1);
}
}
#endif /* BSD2_9 */
#endif /* !BSDINETD */
/* NOTREACHED */
}
static void
struct sockaddr_in *sinp;
{
int error;
alarm(60);
return;
}
/*
* Call pam_start to initiate a PAM authentication operation
*/
return;
return;
/* force a delay if passwd bad */
sleep(4);
return;
}
switch (error) {
case PAM_NEW_AUTHTOK_REQD:
break;
case PAM_PERM_DENIED:
break;
case PAM_AUTHTOK_EXPIRED:
break;
default:
break;
}
return;
}
/* force a delay if user bad */
sleep(4);
return;
}
alarm(0);
if (!nolog)
_exit(1);
}
/* set the real (and effective) GID */
return;
}
/*
* Initialize the supplementary group access list.
*/
return;
}
return;
}
/* set the real (and effective) UID */
return;
}
#endif /* BSD4_2 */
#ifdef BSD2_9
#endif /* BSD2_9 */
perror("uucico server: execl");
}
int
readline(p, n)
char *p;
int n;
{
char c;
while (n-- > 0) {
if (read(0, &c, 1) <= 0)
return (-1);
c &= 0177;
if (c == '\n' || c == '\r') {
*p = '\0';
return (0);
}
*p++ = c;
}
return (-1);
}
#ifdef ATTSVR4
#include <sac.h> /* for SC_WILDC */
#include <utmpx.h>
#else /* !ATTSVR4 */
#include <utmp.h>
#endif /* !ATTSVR4 */
#include <fcntl.h>
#endif /* BSD4_2 */
#ifdef BSD2_9
#endif /* BSD2_9 */
#ifdef ATTSVR4
#else /* !ATTSVR4 */
#endif /* !ATTSVR4 */
static void
dologout(void)
{
#ifdef ATTSVR4
int status;
#else /* !ATTSVR4 */
#endif /* !ATSVR4 */
/* the following 2 variables are needed for utmp mgmt */
#ifdef BSDINETD
#else /* !BSDINETD */
#endif /* !BSDINETD */
if (nolog)
continue;
#ifdef ATTSVR4
/* clear out any residue from utmpx buffer */
/*
* XXX: UUCPD does not do any pam session management.
* There is no way for the parent process to close
* the pam session after a child has exited.
*/
#else /* !ATTSVR4 */
if (wtmp >= 0) {
#ifdef BSD2_9
#endif /* BSD2_9 */
}
#endif /* !ATTSVR4 */
}
}
/*
* Record login in wtmp file.
*/
int
struct sockaddr_in *sin;
{
int wtmp;
if (hp) {
endhostent();
} else
sizeof (remotehost));
#ifdef ATTSVR4
/* clear wtmpx entry */
/* hack, but must be unique and no tty line */
/*
* XXX:
* We no longer do session management in uucpd because
* there is no way to do the "pam_close_session()".
*
* Processes like "init" can do a pam_close_session()
* because they can use the utmp entry to retrieve
* the proper username, ttyname, etc. --
* uucpd only writes to the wtmp file.
*
* ftpd (which also only writes to the wtmp file)
* can do a pam_close_session() because it doesn't fork().
*
* if (pam_set_item(pamh, PAM_RHOST, remotehost) != PAM_SUCCESS)
* return (1);
* if (pam_set_item(pamh, PAM_TTY, line) != PAM_SUCCESS)
* return (1);
* if (pam_open_session(pamh, 0) != PAM_SUCCESS) {
* return (1);
* }
*/
#else /* !ATTSVR4 */
if (wtmp >= 0) {
/* hack, but must be unique and no tty line */
#ifdef BSD2_9
#endif /* BSD2_9 */
}
#endif /* !ATTSVR4 */
return (0);
}
/*
* uucp_conv - This is the conv (conversation) function called from
* a PAM authentication module to print error messages
* or garner information from the user.
*/
static int
int num_msg;
struct pam_message **msg;
struct pam_response **response;
void *appdata_ptr;
{
struct pam_message *m;
struct pam_response *r;
char *temp;
int k, i;
if (num_msg <= 0)
return (PAM_CONV_ERR);
sizeof (struct pam_response));
return (PAM_BUF_ERR);
k = num_msg;
m = *msg;
r = *response;
while (k--) {
switch (m->msg_style) {
case PAM_PROMPT_ECHO_OFF:
/*
* we do this instead of using passed in message
* to prevent possible breakage of uucp protocol.
*/
return (PAM_SUCCESS);
}
/* free responses */
r = *response;
for (i = 0; i < num_msg; i++, r++) {
if (r->resp)
}
return (PAM_BUF_ERR);
}
}
m++;
r++;
break;
case PAM_PROMPT_ECHO_ON:
}
/* free the response */
r = *response;
for (i = 0; i < num_msg; i++, r++) {
if (r->resp)
}
return (PAM_BUF_ERR);
}
m++;
r++;
break;
case PAM_ERROR_MSG:
}
m++;
r++;
break;
case PAM_TEXT_INFO:
}
m++;
r++;
break;
default:
break;
}
}
return (PAM_SUCCESS);
}