1 /* $Id: kftgt.c 2303 2005-12-22 00:58:47Z rra $
3 ** Client program for Kerberos v4 ticket forwarding.
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
27 #ifdef HAVE_KERBEROSIV_KRB_H
28 # include <kerberosIV/krb.h>
37 /** Exit values for various errors. */
51 char **read_options(int argc, char **argv);
52 enum kftgt_error kftgt(char *user, char *server);
53 char *parse_username(char *server,char **ruser);
54 int read_null_term(int s, char *buffer, int max);
55 void warn (char *fmt, ...);
56 int print_version(void);
57 int usage(int exitcode);
62 static char *prog = "kftgt";
65 static char *l_val="";
66 static char *f_val = "";
67 static int t_val=60; /* default timeout */
82 main(int argc, char **argv)
84 enum kftgt_error status = SUCCESS;
86 #ifdef HAVE_DECL_KRB_IGNORE_IP_ADDRESS
87 krb_ignore_ip_address = 1;
90 argv = read_options(argc, argv);
92 char *ruser = l_val, *server;
93 server = parse_username(*argv,&ruser);
94 status = kftgt(ruser, server);
101 parse_username(char *server,char **ruser)
103 char *retval = server;
106 if ((cp = strchr(server,'@')) != NULL) {
117 read_options(int argc, char **argv)
125 /* A quick hack to honor --help and --version */
127 if (argv[1][0] == '-' && argv[1][1] == '-' && argv[1][2] != '\0') {
141 while ((c = getopt(argc, argv, "hl:f:vqdt:")) != EOF) {
143 case 'd': /* Debug */
146 case 'f': /* Ticket File */
152 case 'l': /* User name */
155 case 'q': /* Quiet */
158 case 't': /* Timeout */
170 if (t_val <= 0 || optind >= argc) {
178 kftgt(char *ruser, char *server)
181 struct sockaddr_in saddr, caddr;
194 char buffer[KFTGT_MAX_BUFFER];
197 /* set alarm for timeout */
199 signal(SIGALRM, timeout);
205 memset ((char *) &saddr, 0, sizeof (struct sockaddr_in));
206 if ((se = getservbyname ("kftgt", "tcp")) != NULL ||
207 (se = getservbyport(htons(SERVICE_PORT),"tcp")) != NULL) {
208 saddr.sin_port = se->s_port;
210 saddr.sin_port = htons(SERVICE_PORT);
214 /* First check if valid IP address. Otherwise check if valid name. */
215 if ((addr = inet_addr(server)) != -1) {
216 if ((hp = gethostbyaddr ((char *)&addr, sizeof(unsigned int),
219 fprintf(stderr,"%s: unknown host",server);
223 } else if ((hp = gethostbyname (server)) == NULL) {
225 fprintf(stderr,"%s: unknown host",server);
230 /* Set up socket connection */
231 saddr.sin_family = AF_INET;
232 memcpy (&saddr.sin_addr, hp->h_addr, sizeof(hp->h_addr));
234 if ((sock = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
241 if (connect (sock, (struct sockaddr *) &saddr,
242 sizeof(struct sockaddr_in)) < 0 ) {
246 (void)close(sock); /* Back out */
247 return ERROR_CONNECT;
250 /* copy the hostname into non-volatile storage */
251 remote_host = (char*)malloc(strlen(hp->h_name) + 1);
252 strcpy(remote_host, hp->h_name);
254 /* find out who I am */
255 clen = sizeof(caddr);
256 if (getsockname(sock, (struct sockaddr *) &caddr, &clen) < 0) {
258 perror("getsockname");
264 * call Kerberos library routine to obtain an authenticator,
265 * pass it over the socket to the server, and obtain mutual
269 status = krb_sendauth((KRB_INT32)KOPT_DO_MUTUAL, sock, &ticket,
272 krb_realmofhost(remote_host),
277 &caddr, &saddr, KFTGT_PROTO_VERSION);
279 if (status != KSUCCESS) {
280 warn("cannot authenticate to server: %s",krb_err_txt[status]);
282 return ERROR_KERBEROS;
285 status = read_null_term(sock, buffer, sizeof(buffer));
287 warn("read_null_term failed");
292 if (strncmp(buffer,"ok",2)!=0) {
299 * send over remote user name and ticket file, both NULL terminated
303 if ( (len = marshall_params(ruser, f_val, buffer, sizeof(buffer))) <0) {
304 warn("unable to marshall params");
309 if (send_encrypted_chunk(buffer, len, sock,
310 &cred.session, sched, &caddr, &saddr) < 0) {
311 warn("error sending encrypted params");
316 /* read encrypted response */
318 len = receive_encrypted_chunk(&m_data, buffer, sizeof(buffer), sock,
319 &cred.session, sched, &saddr, &caddr);
321 if (strncmp((char *) m_data.app_data,"ok",2)!=0) {
323 warn("%s",m_data.app_data);
325 warn("error receiving encrypted chunk");
331 /* get realm from cred for now */
333 if (krb_get_cred("krbtgt",cred.realm,cred.realm,&tgtcred) != GC_OK) {
334 warn("cannot get tgt from local ticket file");
336 return ERROR_KERBEROS;
339 len = marshall_cred(&tgtcred,buffer,sizeof(buffer));
341 if (len <= 0 || len > KFTGT_MAX_BUFFER) {
342 warn("marshall of tgt failed");
347 if (send_encrypted_chunk(buffer, len, sock,
348 &cred.session, sched, &caddr, &saddr) < 0) {
349 warn("error sending encrypted user name");
354 len = receive_encrypted_chunk(&m_data,buffer,sizeof(buffer), sock,
355 &cred.session, sched, &saddr, &caddr);
357 if (strncmp((char *) m_data.app_data,"ok",2)!=0) {
359 warn("%s",m_data.app_data);
361 warn("error receiving encrypted chunk");
367 printf("%s: tgt %s.%s@%s forwarded to ",
372 if (ruser[0]) printf("%s at ",ruser);
373 printf("%s\n", server);
382 read_null_term(int s, char *buffer, int max)
388 if ( *buffer == 0 ) return len;
397 * Print error message, terminate connection and download, and exit
399 * fmt format of error message in printf style
400 * ... % arguments supplied for fmt
405 warn (char *fmt, ...)
410 fprintf(stderr,"%s: ",prog);
412 va_start(argptr,fmt);
414 vfprintf(stderr,fmt,argptr);
418 fprintf(stderr,"\n");
424 fprintf(stderr,"%s version %s\n", prog, PACKAGE_VERSION);
431 fprintf(stderr,"Usage: %s [options] [user@]host [user2@host2 ...]\n",prog);
432 fprintf(stderr," -l user remote user to forward tickets to\n");
433 fprintf(stderr," -f file remote ticket filename\n");
434 fprintf(stderr," -t secs timeout, default is 60 seconds\n");
435 fprintf(stderr," -v version\n");
436 fprintf(stderr," -q quiet\n");
437 fprintf(stderr," -d debug info\n");
438 fprintf(stderr,"\n");