1 2 /* 3 * Copyright (c) 1989 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms are permitted 7 * provided that the above copyright notice and this paragraph are 8 * duplicated in all such forms and that any documentation, 9 * advertising materials, and other materials related to such 10 * distribution and use acknowledge that the software was developed 11 * by the University of California, Berkeley. The name of the 12 * University may not be used to endorse or promote products derived 13 * from this software without specific prior written permission. 14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 17 */ 18 19 #ifndef lint 20 static char sccsid[] = "@(#)kpasswd.c 1.2 (Berkeley) 05/17/89"; 21 #endif /* not lint */ 22 23 /* 24 * kpasswd - client program to update Kerberos password 25 * 26 * K. Fall 27 * 12-Dec-88 28 */ 29 30 #include <stdio.h> 31 #include <sys/types.h> 32 #include <sys/time.h> 33 #include <sys/resource.h> 34 #include <sys/socket.h> 35 #include <sys/signal.h> 36 #include <netinet/in.h> 37 #include <netdb.h> 38 #include <kerberos/krb.h> 39 #include "kpasswd_proto.h" 40 41 KTEXT_ST ticket; 42 long authopts = 0L; 43 Key_schedule random_schedule; 44 char realm[REALM_SZ], krbhst[MAX_HSTNM]; 45 static struct kpasswd_data proto_data; 46 static C_Block okey; 47 static Key_schedule osched; 48 static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0 }; 49 int sock; 50 char *getpass(); 51 int sock; 52 53 int finish(); 54 55 #define PROTO "tcp" 56 57 main(argc, argv) 58 int argc; 59 char **argv; 60 { 61 struct servent *se; 62 struct hostent *host; 63 struct sockaddr_in sin; 64 int rval; 65 char password[255], *pass; 66 fd_set readfds; 67 68 static struct rlimit rl = { 0, 0 }; 69 70 signal(SIGHUP, SIG_IGN); 71 signal(SIGINT, SIG_IGN); 72 signal(SIGTSTP, SIG_IGN); 73 74 if(setrlimit(RLIMIT_CORE, &rl) < 0) { 75 perror("setrlimit"); 76 exit(1); 77 } 78 79 if((se = getservbyname(SERVICE, PROTO)) == NULL) { 80 fprintf(stderr, "couldn't find entry for service %s/%s\n", 81 SERVICE, PROTO); 82 exit(1); 83 } 84 if((rval = krb_get_lrealm(realm,1)) != KSUCCESS) { 85 fprintf(stderr, "couldn't get local Kerberos realm: %s\n", 86 krb_err_txt[rval]); 87 exit(1); 88 } 89 90 if((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) { 91 fprintf(stderr, "couldn't get Kerberos host: %s\n", 92 krb_err_txt[rval]); 93 exit(1); 94 } 95 96 if((host = gethostbyname(krbhst)) == NULL) { 97 fprintf(stderr, "couldn't get host entry for host %s\n", 98 krbhst); 99 exit(1); 100 } 101 102 sin.sin_family = host->h_addrtype; 103 bcopy(host->h_addr, (char *) &sin.sin_addr, host->h_length); 104 sin.sin_port = se->s_port; 105 106 if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 107 perror("socket"); 108 exit(1); 109 } 110 111 if(connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { 112 perror("connect"); 113 close(sock); 114 exit(1); 115 } 116 117 rval = krb_sendauth( 118 authopts, /* NOT mutual */ 119 sock, 120 &ticket, /* (filled in) */ 121 SERVICE, 122 krbhst, /* instance (krbhst) */ 123 realm, /* dest realm */ 124 (u_long) getpid(), /* checksum */ 125 NULL, /* msg data */ 126 NULL, /* credentials */ 127 NULL, /* schedule */ 128 NULL, /* local addr */ 129 NULL, /* foreign addr */ 130 "KPWDV0.1" 131 ); 132 133 if(rval != KSUCCESS) { 134 fprintf(stderr, "Kerberos sendauth error: %s\n", 135 krb_err_txt[rval]); 136 exit(1); 137 } 138 139 pass = getpass("Old Kerberos password:"); 140 string_to_key(pass, okey); 141 key_sched(okey, osched); 142 des_set_key(okey, osched); 143 144 /* wait on the verification string */ 145 146 FD_ZERO(&readfds); 147 FD_SET(sock, &readfds); 148 149 rval = 150 select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout); 151 if((rval < 1) || !FD_ISSET(sock, &readfds)) { 152 if(rval == 0) { 153 fprintf(stderr, "Timed out\n"); 154 cleanup(); 155 exit(1); 156 } 157 fprintf(stderr, "select failed\n"); 158 cleanup(); 159 exit(1); 160 } 161 162 /* read verification string */ 163 164 if(des_read(sock, &proto_data, sizeof(proto_data)) != sizeof(proto_data)) { 165 fprintf(stderr, 166 "%s: couldn't read verification string (aborted)\n", 167 argv[0] 168 ); 169 170 cleanup(); 171 exit(1); 172 } 173 174 signal(SIGHUP, finish); 175 signal(SIGINT, finish); 176 177 if(strcmp(SECURE_STRING, proto_data.secure_msg)) { 178 cleanup(); 179 fprintf(stderr, "Sorry.\n"); 180 exit(1); 181 } 182 key_sched(proto_data.random_key, random_schedule); 183 des_set_key(proto_data.random_key, random_schedule); 184 pass = getpass("New Kerberos password:"); 185 strcpy(password, pass); 186 pass = getpass("Retype new Kerberos password:"); 187 if(strcmp(password, pass)) { 188 fprintf(stderr, "Password mismatch (aborted)\n"); 189 cleanup(); 190 exit(1); 191 } 192 send_update(sock, password, SECURE_STRING); 193 194 /* wait for ACK */ 195 196 FD_ZERO(&readfds); 197 FD_SET(sock, &readfds); 198 199 rval = 200 select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout); 201 if((rval < 1) || !FD_ISSET(sock, &readfds)) { 202 if(rval == 0) { 203 fprintf(stderr, "Timed out reading ACK\n"); 204 cleanup(); 205 exit(1); 206 } 207 fprintf(stderr, "select failed\n"); 208 cleanup(); 209 exit(1); 210 } 211 212 recv_ack(sock); 213 cleanup(); 214 exit(0); 215 } 216 217 send_update(dest, pwd, str) 218 int dest; 219 char *pwd, *str; 220 { 221 static struct update_data ud; 222 strncpy(ud.secure_msg, str, MSGSIZE); 223 strncpy(ud.pw, pwd, sizeof(ud.pw)); 224 if(des_write(dest, &ud, sizeof(ud)) != sizeof(ud)) { 225 fprintf(stderr, "couldn't write pw update (abort)\n"); 226 bzero(ud, sizeof(ud)); 227 cleanup(); 228 exit(1); 229 } 230 } 231 232 recv_ack(remote) 233 int remote; 234 { 235 int cc; 236 char buf[BUFSIZ]; 237 cc = des_read(remote, buf, sizeof(buf)); 238 if(cc <= 0) { 239 fprintf(stderr, "error reading acknowledgement\n"); 240 cleanup(); 241 exit(1); 242 } 243 printf("%s", buf); 244 } 245 246 cleanup() 247 { 248 bzero(&proto_data, sizeof(proto_data)); 249 bzero(okey, sizeof(okey)); 250 bzero(osched, sizeof(osched)); 251 bzero(random_schedule, sizeof(random_schedule)); 252 } 253 254 finish() 255 { 256 close(sock); 257 exit(1); 258 } 259