Path: blob/main/crypto/krb5/src/appl/simple/client/sim_client.c
34914 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* appl/simple/client/sim_client.c */2/*3* Copyright 1989,1991 by the Massachusetts Institute of Technology.4* All Rights Reserved.5*6* Export of this software from the United States of America may7* require a specific license from the United States Government.8* It is the responsibility of any person or organization contemplating9* export to obtain such a license before exporting.10*11* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and12* distribute this software and its documentation for any purpose and13* without fee is hereby granted, provided that the above copyright14* notice appear in all copies and that both that copyright notice and15* this permission notice appear in supporting documentation, and that16* the name of M.I.T. not be used in advertising or publicity pertaining17* to distribution of the software without specific, written prior18* permission. Furthermore if you modify this software you must label19* your software as modified software and not distribute it in such a20* fashion that it might be confused with the original M.I.T. software.21* M.I.T. makes no representations about the suitability of22* this software for any purpose. It is provided "as is" without express23* or implied warranty.24*/2526/*27* Simple UDP-based sample client program. For demonstration.28* This program performs no useful function.29*/3031#include <krb5.h>32#include "com_err.h"3334#include <sys/types.h>35#include <sys/socket.h>36#include <netinet/in.h>37#include <stdio.h>38#include <string.h>39#include <errno.h>40#include <netdb.h>41#include <unistd.h>4243#include "simple.h"4445/* for old Unixes and friends ... */46#ifndef MAXHOSTNAMELEN47#define MAXHOSTNAMELEN 6448#endif4950#define MSG "hi there!" /* message text */5152void usage (char *);5354void55usage(char *name)56{57fprintf(stderr, "usage: %s [-p port] [-h host] [-m message] [-s service] [host]\n", name);58}5960int61main(int argc, char *argv[])62{63int sock, i;64socklen_t len;65int flags = 0; /* flags for sendto() */66struct servent *serv;67struct hostent *host;68#ifdef BROKEN_STREAMS_SOCKETS69char my_hostname[MAXHOSTNAMELEN];70#endif71struct sockaddr_in s_sock; /* server address */72struct sockaddr_in c_sock; /* client address */73extern int opterr, optind;74extern char * optarg;75int ch;7677short port = 0;78char *message = MSG;79char *hostname = 0;80char *service = SIMPLE_SERVICE;81char *progname = 0;8283krb5_error_code retval;84krb5_data packet, inbuf;85krb5_ccache ccdef;86krb5_address addr;8788krb5_context context;89krb5_auth_context auth_context = NULL;9091retval = krb5_init_context(&context);92if (retval) {93com_err(argv[0], retval, "while initializing krb5");94exit(1);95}9697progname = argv[0];9899/*100* Parse command line arguments101*102*/103opterr = 0;104while ((ch = getopt(argc, argv, "p:m:h:s:")) != -1)105switch (ch) {106case 'p':107port = atoi(optarg);108break;109case 'm':110message = optarg;111break;112case 'h':113hostname = optarg;114break;115case 's':116service = optarg;117break;118case '?':119default:120usage(progname);121exit(1);122break;123}124argc -= optind;125argv += optind;126if (argc > 0) {127if (hostname)128usage(progname);129hostname = argv[0];130}131132if (hostname == 0) {133fprintf(stderr, "You must specify a hostname to contact.\n\n");134usage(progname);135exit(1);136}137138/* Look up server host */139if ((host = gethostbyname(hostname)) == (struct hostent *) 0) {140fprintf(stderr, "%s: unknown host\n", hostname);141exit(1);142}143144/* Set server's address */145(void) memset(&s_sock, 0, sizeof(s_sock));146147memcpy(&s_sock.sin_addr, host->h_addr, sizeof(s_sock.sin_addr));148#ifdef DEBUG149printf("s_sock.sin_addr is %s\n", inet_ntoa(s_sock.sin_addr));150#endif151s_sock.sin_family = AF_INET;152153if (port == 0) {154/* Look up service */155if ((serv = getservbyname(SIMPLE_PORT, "udp")) == NULL) {156fprintf(stderr, "service unknown: %s/udp\n", SIMPLE_PORT);157exit(1);158}159s_sock.sin_port = serv->s_port;160} else {161s_sock.sin_port = htons(port);162}163164/* Open a socket */165if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {166com_err(progname, errno, "opening datagram socket");167exit(1);168}169170memset(&c_sock, 0, sizeof(c_sock));171c_sock.sin_family = AF_INET;172#ifdef BROKEN_STREAMS_SOCKETS173if (gethostname(my_hostname, sizeof(my_hostname)) < 0) {174perror("gethostname");175exit(1);176}177178if ((host = gethostbyname(my_hostname)) == (struct hostent *)0) {179fprintf(stderr, "%s: unknown host\n", hostname);180exit(1);181}182memcpy(&c_sock.sin_addr, host->h_addr, sizeof(c_sock.sin_addr));183#endif184185186/* Bind it to set the address; kernel will fill in port # */187if (bind(sock, (struct sockaddr *)&c_sock, sizeof(c_sock)) < 0) {188com_err(progname, errno, "while binding datagram socket");189exit(1);190}191192/* PREPARE KRB_AP_REQ MESSAGE */193194inbuf.data = hostname;195inbuf.length = strlen(hostname);196197/* Get credentials for server */198if ((retval = krb5_cc_default(context, &ccdef))) {199com_err(progname, retval, "while getting default ccache");200exit(1);201}202203retval = krb5_mk_req(context, &auth_context, AP_OPTS_USE_SUBKEY, service,204hostname, &inbuf, ccdef, &packet);205if (retval) {206com_err(progname, retval, "while preparing AP_REQ");207exit(1);208}209printf("Got credentials for %s.\n", service);210211/* "connect" the datagram socket; this is necessary to get a local address212properly bound for getsockname() below. */213214if (connect(sock, (struct sockaddr *)&s_sock, sizeof(s_sock)) == -1) {215com_err(progname, errno, "while connecting to server");216exit(1);217}218/* Send authentication info to server */219if ((i = send(sock, (char *)packet.data, (unsigned) packet.length,220flags)) < 0)221com_err(progname, errno, "while sending KRB_AP_REQ message");222printf("Sent authentication data: %d bytes\n", i);223krb5_free_data_contents(context, &packet);224225/* PREPARE KRB_SAFE MESSAGE */226227/* Get my address */228memset(&c_sock, 0, sizeof(c_sock));229len = sizeof(c_sock);230if (getsockname(sock, (struct sockaddr *)&c_sock, &len) < 0) {231com_err(progname, errno, "while getting socket name");232exit(1);233}234235addr.addrtype = ADDRTYPE_IPPORT;236addr.length = sizeof(c_sock.sin_port);237addr.contents = (krb5_octet *)&c_sock.sin_port;238if ((retval = krb5_auth_con_setports(context, auth_context,239&addr, NULL))) {240com_err(progname, retval, "while setting local port\n");241exit(1);242}243244addr.addrtype = ADDRTYPE_INET;245addr.length = sizeof(c_sock.sin_addr);246addr.contents = (krb5_octet *)&c_sock.sin_addr;247if ((retval = krb5_auth_con_setaddrs(context, auth_context,248&addr, NULL))) {249com_err(progname, retval, "while setting local addr\n");250exit(1);251}252253/* Make the safe message */254inbuf.data = message;255inbuf.length = strlen(message);256257if ((retval = krb5_mk_safe(context, auth_context, &inbuf, &packet, NULL))){258com_err(progname, retval, "while making KRB_SAFE message");259exit(1);260}261262/* Send it */263if ((i = send(sock, (char *)packet.data, (unsigned) packet.length,264flags)) < 0)265com_err(progname, errno, "while sending SAFE message");266printf("Sent checksummed message: %d bytes\n", i);267krb5_free_data_contents(context, &packet);268269/* PREPARE KRB_PRIV MESSAGE */270271/* Make the encrypted message */272if ((retval = krb5_mk_priv(context, auth_context, &inbuf,273&packet, NULL))) {274com_err(progname, retval, "while making KRB_PRIV message");275exit(1);276}277278/* Send it */279if ((i = send(sock, (char *)packet.data, (unsigned) packet.length,280flags)) < 0)281com_err(progname, errno, "while sending PRIV message");282printf("Sent encrypted message: %d bytes\n", i);283krb5_free_data_contents(context, &packet);284285krb5_auth_con_free(context, auth_context);286krb5_free_context(context);287288exit(0);289}290291292