1*38050Skfall
236330Skfall /*
3*38050Skfall * Copyright (c) 1989 The Regents of the University of California.
4*38050Skfall * All rights reserved.
536330Skfall *
6*38050Skfall * Redistribution and use in source and binary forms are permitted
7*38050Skfall * provided that the above copyright notice and this paragraph are
8*38050Skfall * duplicated in all such forms and that any documentation,
9*38050Skfall * advertising materials, and other materials related to such
10*38050Skfall * distribution and use acknowledge that the software was developed
11*38050Skfall * by the University of California, Berkeley. The name of the
12*38050Skfall * University may not be used to endorse or promote products derived
13*38050Skfall * from this software without specific prior written permission.
14*38050Skfall * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15*38050Skfall * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16*38050Skfall * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17*38050Skfall */
18*38050Skfall
19*38050Skfall #ifndef lint
20*38050Skfall static char sccsid[] = "@(#)kpasswd.c 1.2 (Berkeley) 05/17/89";
21*38050Skfall #endif /* not lint */
22*38050Skfall
23*38050Skfall /*
24*38050Skfall * kpasswd - client program to update Kerberos password
25*38050Skfall *
2636330Skfall * K. Fall
2736330Skfall * 12-Dec-88
2836330Skfall */
2936330Skfall
3036330Skfall #include <stdio.h>
3136330Skfall #include <sys/types.h>
3236330Skfall #include <sys/time.h>
3336330Skfall #include <sys/resource.h>
3436330Skfall #include <sys/socket.h>
3536330Skfall #include <sys/signal.h>
3636330Skfall #include <netinet/in.h>
3736330Skfall #include <netdb.h>
3836330Skfall #include <kerberos/krb.h>
3936330Skfall #include "kpasswd_proto.h"
4036330Skfall
4136330Skfall KTEXT_ST ticket;
4236330Skfall long authopts = 0L;
4336330Skfall Key_schedule random_schedule;
4436330Skfall char realm[REALM_SZ], krbhst[MAX_HSTNM];
4536330Skfall static struct kpasswd_data proto_data;
4636330Skfall static C_Block okey;
4736330Skfall static Key_schedule osched;
4836330Skfall static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0 };
4936330Skfall int sock;
5036330Skfall char *getpass();
5136330Skfall int sock;
5236330Skfall
5336330Skfall int finish();
5436330Skfall
5536330Skfall #define PROTO "tcp"
5636330Skfall
main(argc,argv)5736330Skfall main(argc, argv)
5836330Skfall int argc;
5936330Skfall char **argv;
6036330Skfall {
6136330Skfall struct servent *se;
6236330Skfall struct hostent *host;
6336330Skfall struct sockaddr_in sin;
6436330Skfall int rval;
6536330Skfall char password[255], *pass;
6636330Skfall fd_set readfds;
6736330Skfall
6836330Skfall static struct rlimit rl = { 0, 0 };
6936330Skfall
7036330Skfall signal(SIGHUP, SIG_IGN);
7136330Skfall signal(SIGINT, SIG_IGN);
7236330Skfall signal(SIGTSTP, SIG_IGN);
7336330Skfall
7436330Skfall if(setrlimit(RLIMIT_CORE, &rl) < 0) {
7536330Skfall perror("setrlimit");
7636330Skfall exit(1);
7736330Skfall }
7836330Skfall
7936330Skfall if((se = getservbyname(SERVICE, PROTO)) == NULL) {
8036330Skfall fprintf(stderr, "couldn't find entry for service %s/%s\n",
8136330Skfall SERVICE, PROTO);
8236330Skfall exit(1);
8336330Skfall }
84*38050Skfall if((rval = krb_get_lrealm(realm,1)) != KSUCCESS) {
8536330Skfall fprintf(stderr, "couldn't get local Kerberos realm: %s\n",
8636330Skfall krb_err_txt[rval]);
8736330Skfall exit(1);
8836330Skfall }
8936330Skfall
90*38050Skfall if((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) {
9136330Skfall fprintf(stderr, "couldn't get Kerberos host: %s\n",
9236330Skfall krb_err_txt[rval]);
9336330Skfall exit(1);
9436330Skfall }
9536330Skfall
9636330Skfall if((host = gethostbyname(krbhst)) == NULL) {
9736330Skfall fprintf(stderr, "couldn't get host entry for host %s\n",
9836330Skfall krbhst);
9936330Skfall exit(1);
10036330Skfall }
10136330Skfall
10236330Skfall sin.sin_family = host->h_addrtype;
10336330Skfall bcopy(host->h_addr, (char *) &sin.sin_addr, host->h_length);
10436330Skfall sin.sin_port = se->s_port;
10536330Skfall
10636330Skfall if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
10736330Skfall perror("socket");
10836330Skfall exit(1);
10936330Skfall }
11036330Skfall
11136330Skfall if(connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
11236330Skfall perror("connect");
11336330Skfall close(sock);
11436330Skfall exit(1);
11536330Skfall }
11636330Skfall
11736330Skfall rval = krb_sendauth(
11836330Skfall authopts, /* NOT mutual */
11936330Skfall sock,
12036330Skfall &ticket, /* (filled in) */
12136330Skfall SERVICE,
12236330Skfall krbhst, /* instance (krbhst) */
12336330Skfall realm, /* dest realm */
12436330Skfall (u_long) getpid(), /* checksum */
12536330Skfall NULL, /* msg data */
12636330Skfall NULL, /* credentials */
12736330Skfall NULL, /* schedule */
12836330Skfall NULL, /* local addr */
12936330Skfall NULL, /* foreign addr */
13036330Skfall "KPWDV0.1"
13136330Skfall );
13236330Skfall
13336330Skfall if(rval != KSUCCESS) {
13436330Skfall fprintf(stderr, "Kerberos sendauth error: %s\n",
13536330Skfall krb_err_txt[rval]);
13636330Skfall exit(1);
13736330Skfall }
13836330Skfall
13936330Skfall pass = getpass("Old Kerberos password:");
14036330Skfall string_to_key(pass, okey);
14136330Skfall key_sched(okey, osched);
14236330Skfall des_set_key(okey, osched);
14336330Skfall
14436330Skfall /* wait on the verification string */
14536330Skfall
14636330Skfall FD_ZERO(&readfds);
14736330Skfall FD_SET(sock, &readfds);
14836330Skfall
14936330Skfall rval =
15036330Skfall select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
15136330Skfall if((rval < 1) || !FD_ISSET(sock, &readfds)) {
15236330Skfall if(rval == 0) {
15336330Skfall fprintf(stderr, "Timed out\n");
15436330Skfall cleanup();
15536330Skfall exit(1);
15636330Skfall }
15736330Skfall fprintf(stderr, "select failed\n");
15836330Skfall cleanup();
15936330Skfall exit(1);
16036330Skfall }
16136330Skfall
16236330Skfall /* read verification string */
16336330Skfall
16436330Skfall if(des_read(sock, &proto_data, sizeof(proto_data)) != sizeof(proto_data)) {
16536330Skfall fprintf(stderr,
16636330Skfall "%s: couldn't read verification string (aborted)\n",
16736330Skfall argv[0]
16836330Skfall );
16936330Skfall
17036330Skfall cleanup();
17136330Skfall exit(1);
17236330Skfall }
17336330Skfall
17436330Skfall signal(SIGHUP, finish);
17536330Skfall signal(SIGINT, finish);
17636330Skfall
17736330Skfall if(strcmp(SECURE_STRING, proto_data.secure_msg)) {
17836330Skfall cleanup();
17936330Skfall fprintf(stderr, "Sorry.\n");
18036330Skfall exit(1);
18136330Skfall }
18236330Skfall key_sched(proto_data.random_key, random_schedule);
18336330Skfall des_set_key(proto_data.random_key, random_schedule);
18436330Skfall pass = getpass("New Kerberos password:");
18536330Skfall strcpy(password, pass);
18636330Skfall pass = getpass("Retype new Kerberos password:");
18736330Skfall if(strcmp(password, pass)) {
18836330Skfall fprintf(stderr, "Password mismatch (aborted)\n");
18936330Skfall cleanup();
19036330Skfall exit(1);
19136330Skfall }
19236330Skfall send_update(sock, password, SECURE_STRING);
19336330Skfall
19436330Skfall /* wait for ACK */
19536330Skfall
19636330Skfall FD_ZERO(&readfds);
19736330Skfall FD_SET(sock, &readfds);
19836330Skfall
19936330Skfall rval =
20036330Skfall select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
20136330Skfall if((rval < 1) || !FD_ISSET(sock, &readfds)) {
20236330Skfall if(rval == 0) {
20336330Skfall fprintf(stderr, "Timed out reading ACK\n");
20436330Skfall cleanup();
20536330Skfall exit(1);
20636330Skfall }
20736330Skfall fprintf(stderr, "select failed\n");
20836330Skfall cleanup();
20936330Skfall exit(1);
21036330Skfall }
21136330Skfall
21236330Skfall recv_ack(sock);
21336330Skfall cleanup();
21436330Skfall exit(0);
21536330Skfall }
21636330Skfall
send_update(dest,pwd,str)21736330Skfall send_update(dest, pwd, str)
21836330Skfall int dest;
21936330Skfall char *pwd, *str;
22036330Skfall {
22136330Skfall static struct update_data ud;
22236330Skfall strncpy(ud.secure_msg, str, MSGSIZE);
22336330Skfall strncpy(ud.pw, pwd, sizeof(ud.pw));
22436330Skfall if(des_write(dest, &ud, sizeof(ud)) != sizeof(ud)) {
22536330Skfall fprintf(stderr, "couldn't write pw update (abort)\n");
22636330Skfall bzero(ud, sizeof(ud));
22736330Skfall cleanup();
22836330Skfall exit(1);
22936330Skfall }
23036330Skfall }
23136330Skfall
recv_ack(remote)23236330Skfall recv_ack(remote)
23336330Skfall int remote;
23436330Skfall {
23536330Skfall int cc;
23636330Skfall char buf[BUFSIZ];
23736330Skfall cc = des_read(remote, buf, sizeof(buf));
23836330Skfall if(cc <= 0) {
23936330Skfall fprintf(stderr, "error reading acknowledgement\n");
24036330Skfall cleanup();
24136330Skfall exit(1);
24236330Skfall }
24336330Skfall printf("%s", buf);
24436330Skfall }
24536330Skfall
cleanup()24636330Skfall cleanup()
24736330Skfall {
24836330Skfall bzero(&proto_data, sizeof(proto_data));
24936330Skfall bzero(okey, sizeof(okey));
25036330Skfall bzero(osched, sizeof(osched));
25136330Skfall bzero(random_schedule, sizeof(random_schedule));
25236330Skfall }
25336330Skfall
finish()25436330Skfall finish()
25536330Skfall {
25636330Skfall close(sock);
25736330Skfall exit(1);
25836330Skfall }
259