Path: blob/main/crypto/krb5/src/appl/sample/sclient/sclient.c
34889 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* appl/sample/sclient/sclient.c */2/*3* Copyright 1990,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*28* Sample Kerberos v5 client.29*30* Usage: sample_client hostname31*/3233#include "krb5.h"34#include "com_err.h"3536#include <stdio.h>37#include <string.h>38#include <ctype.h>39#include <errno.h>4041#include <sys/types.h>42#include <sys/socket.h>43#include <netinet/in.h>44#include <netdb.h>45#include "fake-addrinfo.h" /* not everyone implements getaddrinfo yet */4647#include <signal.h>4849#ifdef HAVE_UNISTD_H50#include <unistd.h>51#endif5253#include <stdlib.h>5455#include "../sample.h"5657#ifndef GETSOCKNAME_ARG3_TYPE58#define GETSOCKNAME_ARG3_TYPE int59#endif6061static int62net_read(int fd, char *buf, int len)63{64int cc, len2 = 0;6566do {67cc = SOCKET_READ((SOCKET)fd, buf, len);68if (cc < 0) {69if (SOCKET_ERRNO == SOCKET_EINTR)70continue;7172/* XXX this interface sucks! */73errno = SOCKET_ERRNO;7475return(cc); /* errno is already set */76}77else if (cc == 0) {78return(len2);79} else {80buf += cc;81len2 += cc;82len -= cc;83}84} while (len > 0);85return(len2);86}8788int89main(int argc, char *argv[])90{91struct addrinfo *ap, aihints, *apstart;92int aierr;93int sock;94krb5_context context;95krb5_data recv_data;96krb5_data cksum_data;97krb5_error_code retval;98krb5_ccache ccdef;99krb5_principal client, server;100krb5_error *err_ret;101krb5_ap_rep_enc_part *rep_ret;102krb5_auth_context auth_context = 0;103short xmitlen;104char *portstr;105char *service = SAMPLE_SERVICE;106107if (argc != 2 && argc != 3 && argc != 4) {108fprintf(stderr, "usage: %s <hostname> [port] [service]\n",argv[0]);109exit(1);110}111112retval = krb5_init_context(&context);113if (retval) {114com_err(argv[0], retval, "while initializing krb5");115exit(1);116}117118(void) signal(SIGPIPE, SIG_IGN);119120if (argc > 2)121portstr = argv[2];122else123portstr = SAMPLE_PORT;124125memset(&aihints, 0, sizeof(aihints));126aihints.ai_socktype = SOCK_STREAM;127aihints.ai_flags = AI_ADDRCONFIG;128aierr = getaddrinfo(argv[1], portstr, &aihints, &ap);129if (aierr) {130fprintf(stderr, "%s: error looking up host '%s' port '%s'/tcp: %s\n",131argv[0], argv[1], portstr, gai_strerror(aierr));132exit(1);133}134if (ap == 0) {135/* Should never happen. */136fprintf(stderr, "%s: error looking up host '%s' port '%s'/tcp: no addresses returned?\n",137argv[0], argv[1], portstr);138exit(1);139}140141if (argc > 3) {142service = argv[3];143}144145retval = krb5_sname_to_principal(context, argv[1], service,146KRB5_NT_SRV_HST, &server);147if (retval) {148com_err(argv[0], retval, "while creating server name for host %s service %s",149argv[1], service);150exit(1);151}152153/* set up the address of the foreign socket for connect() */154apstart = ap; /* For freeing later */155for (sock = -1; ap && sock == -1; ap = ap->ai_next) {156char abuf[NI_MAXHOST], pbuf[NI_MAXSERV];157char mbuf[NI_MAXHOST + NI_MAXSERV + 64];158if (getnameinfo(ap->ai_addr, ap->ai_addrlen, abuf, sizeof(abuf),159pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {160memset(abuf, 0, sizeof(abuf));161memset(pbuf, 0, sizeof(pbuf));162strncpy(abuf, "[error, cannot print address?]",163sizeof(abuf)-1);164strncpy(pbuf, "[?]", sizeof(pbuf)-1);165}166memset(mbuf, 0, sizeof(mbuf));167strncpy(mbuf, "error contacting ", sizeof(mbuf)-1);168strncat(mbuf, abuf, sizeof(mbuf) - strlen(mbuf) - 1);169strncat(mbuf, " port ", sizeof(mbuf) - strlen(mbuf) - 1);170strncat(mbuf, pbuf, sizeof(mbuf) - strlen(mbuf) - 1);171sock = socket(ap->ai_family, SOCK_STREAM, 0);172if (sock < 0) {173fprintf(stderr, "%s: socket: %s\n", mbuf, strerror(errno));174continue;175}176if (connect(sock, ap->ai_addr, ap->ai_addrlen) < 0) {177fprintf(stderr, "%s: connect: %s\n", mbuf, strerror(errno));178close(sock);179sock = -1;180continue;181}182/* connected, yay! */183}184if (sock == -1)185/* Already printed error message above. */186exit(1);187printf("connected\n");188189cksum_data.data = argv[1];190cksum_data.length = strlen(argv[1]);191192retval = krb5_cc_default(context, &ccdef);193if (retval) {194com_err(argv[0], retval, "while getting default ccache");195exit(1);196}197198retval = krb5_cc_get_principal(context, ccdef, &client);199if (retval) {200com_err(argv[0], retval, "while getting client principal name");201exit(1);202}203retval = krb5_sendauth(context, &auth_context, (krb5_pointer) &sock,204SAMPLE_VERSION, client, server,205AP_OPTS_MUTUAL_REQUIRED,206&cksum_data,2070, /* no creds, use ccache instead */208ccdef, &err_ret, &rep_ret, NULL);209210krb5_free_principal(context, server); /* finished using it */211krb5_free_principal(context, client);212krb5_cc_close(context, ccdef);213if (auth_context) krb5_auth_con_free(context, auth_context);214215if (retval && retval != KRB5_SENDAUTH_REJECTED) {216com_err(argv[0], retval, "while using sendauth");217exit(1);218}219if (retval == KRB5_SENDAUTH_REJECTED) {220/* got an error */221printf("sendauth rejected, error reply is:\n\t\"%*s\"\n",222err_ret->text.length, err_ret->text.data);223} else if (rep_ret) {224/* got a reply */225krb5_free_ap_rep_enc_part(context, rep_ret);226227printf("sendauth succeeded, reply is:\n");228if ((retval = net_read(sock, (char *)&xmitlen,229sizeof(xmitlen))) <= 0) {230if (retval == 0)231errno = ECONNABORTED;232com_err(argv[0], errno, "while reading data from server");233exit(1);234}235recv_data.length = ntohs(xmitlen);236if (!(recv_data.data = (char *)malloc((size_t) recv_data.length + 1))) {237com_err(argv[0], ENOMEM,238"while allocating buffer to read from server");239exit(1);240}241if ((retval = net_read(sock, (char *)recv_data.data,242recv_data.length)) <= 0) {243if (retval == 0)244errno = ECONNABORTED;245com_err(argv[0], errno, "while reading data from server");246exit(1);247}248recv_data.data[recv_data.length] = '\0';249printf("reply len %d, contents:\n%s\n",250recv_data.length,recv_data.data);251free(recv_data.data);252} else {253com_err(argv[0], 0, "no error or reply from sendauth!");254exit(1);255}256freeaddrinfo(apstart);257krb5_free_context(context);258exit(0);259}260261262