diff options
Diffstat (limited to 'src/appl/simple/client/sim_client.c')
| -rw-r--r-- | src/appl/simple/client/sim_client.c | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/src/appl/simple/client/sim_client.c b/src/appl/simple/client/sim_client.c new file mode 100644 index 000000000000..bd3c38c72aa7 --- /dev/null +++ b/src/appl/simple/client/sim_client.c @@ -0,0 +1,323 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* appl/simple/client/sim_client.c */ +/* + * Copyright 1989,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Simple UDP-based sample client program. For demonstration. + * This program performs no useful function. + */ + +#include <k5-int.h> +#include "com_err.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <ctype.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "simple.h" + +/* for old Unixes and friends ... */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#define MSG "hi there!" /* message text */ + +void usage (char *); + +void +usage(char *name) +{ + fprintf(stderr, "usage: %s [-p port] [-h host] [-m message] [-s service] [host]\n", name); +} + +int +main(int argc, char *argv[]) +{ + int sock, i; + unsigned int len; + int flags = 0; /* flags for sendto() */ + struct servent *serv; + struct hostent *host; + char *cp; +#ifdef BROKEN_STREAMS_SOCKETS + char my_hostname[MAXHOSTNAMELEN]; +#endif + struct sockaddr_in s_sock; /* server address */ + struct sockaddr_in c_sock; /* client address */ + extern int opterr, optind; + extern char * optarg; + int ch; + + short port = 0; + char *message = MSG; + char *hostname = 0; + char *service = SIMPLE_SERVICE; + char *progname = 0; + + krb5_error_code retval; + krb5_data packet, inbuf; + krb5_ccache ccdef; + krb5_address addr, *portlocal_addr; + krb5_rcache rcache; + krb5_data rcache_name; + + krb5_context context; + krb5_auth_context auth_context = NULL; + + retval = krb5_init_context(&context); + if (retval) { + com_err(argv[0], retval, "while initializing krb5"); + exit(1); + } + + progname = argv[0]; + + /* + * Parse command line arguments + * + */ + opterr = 0; + while ((ch = getopt(argc, argv, "p:m:h:s:")) != -1) + switch (ch) { + case 'p': + port = atoi(optarg); + break; + case 'm': + message = optarg; + break; + case 'h': + hostname = optarg; + break; + case 's': + service = optarg; + break; + case '?': + default: + usage(progname); + exit(1); + break; + } + argc -= optind; + argv += optind; + if (argc > 0) { + if (hostname) + usage(progname); + hostname = argv[0]; + } + + if (hostname == 0) { + fprintf(stderr, "You must specify a hostname to contact.\n\n"); + usage(progname); + exit(1); + } + + /* Look up server host */ + if ((host = gethostbyname(hostname)) == (struct hostent *) 0) { + fprintf(stderr, "%s: unknown host\n", hostname); + exit(1); + } + + /* Set server's address */ + (void) memset(&s_sock, 0, sizeof(s_sock)); + + memcpy(&s_sock.sin_addr, host->h_addr, sizeof(s_sock.sin_addr)); +#ifdef DEBUG + printf("s_sock.sin_addr is %s\n", inet_ntoa(s_sock.sin_addr)); +#endif + s_sock.sin_family = AF_INET; + + if (port == 0) { + /* Look up service */ + if ((serv = getservbyname(SIMPLE_PORT, "udp")) == NULL) { + fprintf(stderr, "service unknown: %s/udp\n", SIMPLE_PORT); + exit(1); + } + s_sock.sin_port = serv->s_port; + } else { + s_sock.sin_port = htons(port); + } + + /* Open a socket */ + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + com_err(progname, errno, "opening datagram socket"); + exit(1); + } + + memset(&c_sock, 0, sizeof(c_sock)); + c_sock.sin_family = AF_INET; +#ifdef BROKEN_STREAMS_SOCKETS + if (gethostname(my_hostname, sizeof(my_hostname)) < 0) { + perror("gethostname"); + exit(1); + } + + if ((host = gethostbyname(my_hostname)) == (struct hostent *)0) { + fprintf(stderr, "%s: unknown host\n", hostname); + exit(1); + } + memcpy(&c_sock.sin_addr, host->h_addr, sizeof(c_sock.sin_addr)); +#endif + + + /* Bind it to set the address; kernel will fill in port # */ + if (bind(sock, (struct sockaddr *)&c_sock, sizeof(c_sock)) < 0) { + com_err(progname, errno, "while binding datagram socket"); + exit(1); + } + + /* PREPARE KRB_AP_REQ MESSAGE */ + + inbuf.data = hostname; + inbuf.length = strlen(hostname); + + /* Get credentials for server */ + if ((retval = krb5_cc_default(context, &ccdef))) { + com_err(progname, retval, "while getting default ccache"); + exit(1); + } + + if ((retval = krb5_mk_req(context, &auth_context, 0, service, hostname, + &inbuf, ccdef, &packet))) { + com_err(progname, retval, "while preparing AP_REQ"); + exit(1); + } + printf("Got credentials for %s.\n", service); + + /* "connect" the datagram socket; this is necessary to get a local address + properly bound for getsockname() below. */ + + if (connect(sock, (struct sockaddr *)&s_sock, sizeof(s_sock)) == -1) { + com_err(progname, errno, "while connecting to server"); + exit(1); + } + /* Send authentication info to server */ + if ((i = send(sock, (char *)packet.data, (unsigned) packet.length, + flags)) < 0) + com_err(progname, errno, "while sending KRB_AP_REQ message"); + printf("Sent authentication data: %d bytes\n", i); + krb5_free_data_contents(context, &packet); + + /* PREPARE KRB_SAFE MESSAGE */ + + /* Get my address */ + memset(&c_sock, 0, sizeof(c_sock)); + len = sizeof(c_sock); + if (getsockname(sock, (struct sockaddr *)&c_sock, &len) < 0) { + com_err(progname, errno, "while getting socket name"); + exit(1); + } + + addr.addrtype = ADDRTYPE_IPPORT; + addr.length = sizeof(c_sock.sin_port); + addr.contents = (krb5_octet *)&c_sock.sin_port; + if ((retval = krb5_auth_con_setports(context, auth_context, + &addr, NULL))) { + com_err(progname, retval, "while setting local port\n"); + exit(1); + } + + addr.addrtype = ADDRTYPE_INET; + addr.length = sizeof(c_sock.sin_addr); + addr.contents = (krb5_octet *)&c_sock.sin_addr; + if ((retval = krb5_auth_con_setaddrs(context, auth_context, + &addr, NULL))) { + com_err(progname, retval, "while setting local addr\n"); + exit(1); + } + + /* THIS IS UGLY */ + if ((retval = krb5_gen_portaddr(context, &addr, + (krb5_pointer) &c_sock.sin_port, + &portlocal_addr))) { + com_err(progname, retval, "while generating port address"); + exit(1); + } + + if ((retval = krb5_gen_replay_name(context,portlocal_addr, + "_sim_clt",&cp))) { + com_err(progname, retval, "while generating replay cache name"); + exit(1); + } + + rcache_name.length = strlen(cp); + rcache_name.data = cp; + + if ((retval = krb5_get_server_rcache(context, &rcache_name, &rcache))) { + com_err(progname, retval, "while getting server rcache"); + exit(1); + } + + /* set auth_context rcache */ + krb5_auth_con_setrcache(context, auth_context, rcache); + + /* Make the safe message */ + inbuf.data = message; + inbuf.length = strlen(message); + + if ((retval = krb5_mk_safe(context, auth_context, &inbuf, &packet, NULL))){ + com_err(progname, retval, "while making KRB_SAFE message"); + exit(1); + } + + /* Send it */ + if ((i = send(sock, (char *)packet.data, (unsigned) packet.length, + flags)) < 0) + com_err(progname, errno, "while sending SAFE message"); + printf("Sent checksummed message: %d bytes\n", i); + krb5_free_data_contents(context, &packet); + + /* PREPARE KRB_PRIV MESSAGE */ + + /* Make the encrypted message */ + if ((retval = krb5_mk_priv(context, auth_context, &inbuf, + &packet, NULL))) { + com_err(progname, retval, "while making KRB_PRIV message"); + exit(1); + } + + /* Send it */ + if ((i = send(sock, (char *)packet.data, (unsigned) packet.length, + flags)) < 0) + com_err(progname, errno, "while sending PRIV message"); + printf("Sent encrypted message: %d bytes\n", i); + krb5_free_data_contents(context, &packet); + + retval = krb5_rc_destroy(context, rcache); + if (retval) { + com_err(progname, retval, "while deleting replay cache"); + exit(1); + } + krb5_auth_con_setrcache(context, auth_context, NULL); + krb5_auth_con_free(context, auth_context); + krb5_free_context(context); + + exit(0); +} |
