4.4BSD/usr/src/old/athena/register/register.c

Compare this file to the similar file:
Show the results in this format:

/*
 * Copyright (c) 1989 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
static char sccsid[] = "@(#)register.c	1.5 (Berkeley) 5/17/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <kerberos/krb.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/signal.h>
#include "register_proto.h"

#define	SERVICE	"krbupdate"
#define	PROTO	"tcp"
#define	KFILE	"/.update.key%s"
#define	KPASSWD	"/usr/athena/kpasswd"

char	realm[REALM_SZ];
char	krbhst[MAX_HSTNM];

static	char	pname[ANAME_SZ];
static	char	iname[INST_SZ];
static	char	password[255];

extern char	*sys_errlist;
int	die();

main(argc, argv)
int	argc;
char	**argv;
{
	struct servent	*se;
	struct hostent	*host;
	struct sockaddr_in	sin, local;
	int		rval;
	int		sock, llen;
	u_char		code;
	static struct rlimit rl = { 0, 0 };

	signal(SIGPIPE, die);

	if (setrlimit(RLIMIT_CORE, &rl) < 0) {
		perror("rlimit");
		exit(1);
	}

	if ((se = getservbyname(SERVICE, PROTO)) == NULL) {
		fprintf(stderr, "couldn't find entry for service %s\n",
			SERVICE);
		exit(1);
	}
	if ((rval = krb_get_lrealm(realm,1)) != KSUCCESS) {
		fprintf(stderr, "couldn't get local Kerberos realm: %s\n",
			krb_err_txt[rval]);
		exit(1);
	}

	if ((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) {
		fprintf(stderr, "couldn't get Kerberos host: %s\n",
			krb_err_txt[rval]);
		exit(1);
	}

	if ((host = gethostbyname(krbhst)) == NULL) {
		fprintf(stderr, "couldn't get host entry for host %s\n",
			krbhst);
		exit(1);
	}

	sin.sin_family = host->h_addrtype;
	bcopy(host->h_addr, (char *) &sin.sin_addr, host->h_length);
	sin.sin_port = se->s_port;

	if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
		perror("socket");
		exit(1);
	}

	if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
		perror("connect");
		close(sock);
		exit(1);
	}

	llen = sizeof(local);
	if (getsockname(sock, (struct sockaddr *) &local, &llen) < 0) {
		perror("getsockname");
		close(sock);
		exit(1);
	}

	setup_key(local);

	type_info();

	if (!get_user_info()) {
		code = ABORT;
		(void)des_write(sock, &code, 1);
		cleanup();
		exit(1);
	}

	code = APPEND_DB;
	if(des_write(sock, &code, 1) != 1) {
		perror("write 1");
		cleanup();
		exit(1);
	}

	if(des_write(sock, pname, ANAME_SZ) != ANAME_SZ) {
		perror("write principal name");
		cleanup();
		exit(1);
	}

	if(des_write(sock, iname, INST_SZ) != INST_SZ) {
		perror("write instance name");
		cleanup();
		exit(1);
	}

	if(des_write(sock, password, 255) != 255) {
		perror("write password");
		cleanup();
		exit(1);
	}

	/* get return message */

	{
		int	cc;
		char	msgbuf[BUFSIZ];

		cc = read(sock, msgbuf, BUFSIZ);
		if (cc <= 0) {
			fprintf(stderr, "protocol error during key verification\n");
			cleanup();
			exit(1);
		}
		if (strncmp(msgbuf, GOTKEY_MSG, 6) != 0) {
			fprintf(stderr, "%s: %s", krbhst, msgbuf);
			cleanup();
			exit(1);
		}

		cc = des_read(sock, msgbuf, BUFSIZ);
		if(cc <= 0) {
			fprintf(stderr, "protocol error during read\n");
			cleanup();
			exit(1);
		} else {
			printf("%s: %s", krbhst, msgbuf);
		}
	}

	cleanup();
	close(sock);
}

cleanup()
{
	bzero(password, 255);
}

#include <pwd.h>

extern	char	*crypt();
extern	char	*getpass();

int
get_user_info()
{
	int	uid = getuid();
	int	valid = 0, i;
	struct	passwd	*pw;
	char	*pas, *namep;

	if((pw = getpwuid(uid)) == NULL) {
		fprintf(stderr, "Who are you?\n");
		return(0);
	}
	seteuid(uid);
	strcpy(pname, pw->pw_name);	/* principal name */
	for(i = 1; i < 3; i++) {
		pas = getpass("login password:");
		namep = crypt(pas, pw->pw_passwd);
		if(strcmp(namep, pw->pw_passwd)) {
			fprintf(stderr, "Password incorrect\n");
			continue;
		} else {
			valid = 1;
			break;
		}
	}
	if(!valid)
		return(0);
	pas = getpass("Kerberos password (may be the same):");
	while(*pas == NULL) {
		printf("<NULL> password not allowed\n");
		pas = getpass("Kerberos password (may be the same):");
	}
	strcpy(password, pas);		/* password */
	pas = getpass("Retype Kerberos password:");
	if(strcmp(password, pas)) {
		fprintf(stderr, "Password mismatch -- aborted\n");
		return(0);
	}

	iname[0] = NULL;	/* null instance name */
	return(1);
}

setup_key(local)
	struct	sockaddr_in	local;
{
	static	struct	keyfile_data	kdata;
	static  Key_schedule		schedule;
	int	fd;
	char	namebuf[MAXPATHLEN];
	extern int errno;

	sprintf(namebuf, KFILE, inet_ntoa(local.sin_addr));
	fd = open(namebuf, O_RDONLY);
	if(fd < 0) {
		fprintf(stderr, "couldn't open key file for local host %s\n",
			inet_ntoa(local.sin_addr));
		perror("open");
		exit(1);
	}

	if(read(fd, (char *)&kdata, sizeof(kdata)) != sizeof(kdata)) {
		fprintf(stderr,"size error reading key file for local host %s\n",
			inet_ntoa(local.sin_addr));
		exit(1);
	}
	key_sched(kdata.kf_key, schedule);
	des_set_key(kdata.kf_key, schedule);
}

type_info()
{
	printf("Kerberos user registration (realm %s)\n\n", realm);
	printf("Please enter your login password followed by your new Kerberos password.\n");
	printf("The Kerberos password you enter now will be used in the future\n");
	printf("as your Kerberos password for all machines in the %s realm.\n", realm);
	printf("You will only be allowed to perform this operation once, although you may run\n");
	printf("the %s program from now on to change your Kerberos password.\n\n", KPASSWD);
}

die()
{
	fprintf(stderr, "\nServer no longer listeninga\n");
	fflush(stderr);
	cleanup();
	exit(1);
}