Path: blob/main/crypto/krb5/src/appl/sample/sserver/sserver.c
34890 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* appl/sample/sserver/sserver.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* Sample Kerberos v5 server.28*29* sample_server:30* A sample Kerberos server, which reads an AP_REQ from a TCP socket,31* decodes it, and writes back the results (in ASCII) to the client.32*33* Usage:34* sample_server servername35*36* file descriptor 0 (zero) should be a socket connected to the requesting37* client (this will be correct if this server is started by inetd).38*/3940#include "k5-int.h"41#include "com_err.h"4243#include <stdio.h>44#include <string.h>45#include <ctype.h>46#include <sys/types.h>47#include <sys/socket.h>48#include <netinet/in.h>49#include <netdb.h>50#include <syslog.h>5152#ifdef HAVE_UNISTD_H53#include <unistd.h>54#endif5556#include "../sample.h"5758extern krb5_deltat krb5_clockskew;5960#ifndef GETPEERNAME_ARG3_TYPE61#define GETPEERNAME_ARG3_TYPE int62#endif6364static void65usage(char *name)66{67fprintf(stderr, "usage: %s [-p port] [-s service] [-S keytab]\n",68name);69}7071int72main(int argc, char *argv[])73{74krb5_context context;75krb5_auth_context auth_context = NULL;76krb5_ticket * ticket;77struct sockaddr_in peername;78GETPEERNAME_ARG3_TYPE namelen = sizeof(peername);79int sock = -1; /* incoming connection fd */80krb5_data recv_data;81short xmitlen;82krb5_error_code retval;83krb5_principal server;84char repbuf[BUFSIZ];85char *cname;86char *service = SAMPLE_SERVICE;87short port = 0; /* If user specifies port */88extern int opterr, optind;89extern char * optarg;90int ch;91krb5_keytab keytab = NULL; /* Allow specification on command line */92char *progname;93int on = 1;9495progname = *argv;9697retval = krb5_init_context(&context);98if (retval) {99com_err(argv[0], retval, "while initializing krb5");100exit(1);101}102103/* open a log connection */104openlog("sserver", 0, LOG_DAEMON);105106/*107* Parse command line arguments108*109*/110opterr = 0;111while ((ch = getopt(argc, argv, "p:S:s:")) != -1) {112switch (ch) {113case 'p':114port = atoi(optarg);115break;116case 's':117service = optarg;118break;119case 'S':120if ((retval = krb5_kt_resolve(context, optarg, &keytab))) {121com_err(progname, retval,122"while resolving keytab file %s", optarg);123exit(2);124}125break;126127case '?':128default:129usage(progname);130exit(1);131break;132}133}134135argc -= optind;136argv += optind;137138/* Backwards compatibility, allow port to be specified at end */139if (argc > 1) {140port = atoi(argv[1]);141}142143retval = krb5_sname_to_principal(context, NULL, service,144KRB5_NT_SRV_HST, &server);145if (retval) {146syslog(LOG_ERR, "while generating service name (%s): %s",147service, error_message(retval));148exit(1);149}150151/*152* If user specified a port, then listen on that port; otherwise,153* assume we've been started out of inetd.154*/155156if (port) {157int acc;158struct sockaddr_in sockin;159160if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {161syslog(LOG_ERR, "socket: %m");162exit(3);163}164/* Let the socket be reused right away */165(void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on,166sizeof(on));167168sockin.sin_family = AF_INET;169sockin.sin_addr.s_addr = 0;170sockin.sin_port = htons(port);171if (bind(sock, (struct sockaddr *) &sockin, sizeof(sockin))) {172syslog(LOG_ERR, "bind: %m");173exit(3);174}175if (listen(sock, 1) == -1) {176syslog(LOG_ERR, "listen: %m");177exit(3);178}179180printf("starting...\n");181fflush(stdout);182183if ((acc = accept(sock, (struct sockaddr *)&peername, &namelen)) == -1){184syslog(LOG_ERR, "accept: %m");185exit(3);186}187dup2(acc, 0);188close(sock);189sock = 0;190} else {191/*192* To verify authenticity, we need to know the address of the193* client.194*/195if (getpeername(0, (struct sockaddr *)&peername, &namelen) < 0) {196syslog(LOG_ERR, "getpeername: %m");197exit(1);198}199sock = 0;200}201202retval = krb5_recvauth(context, &auth_context, (krb5_pointer)&sock,203SAMPLE_VERSION, server,2040, /* no flags */205keytab, /* default keytab is NULL */206&ticket);207if (retval) {208syslog(LOG_ERR, "recvauth failed--%s", error_message(retval));209exit(1);210}211212/* Get client name */213repbuf[sizeof(repbuf) - 1] = '\0';214retval = krb5_unparse_name(context, ticket->enc_part2->client, &cname);215if (retval){216syslog(LOG_ERR, "unparse failed: %s", error_message(retval));217strncpy(repbuf, "You are <unparse error>\n", sizeof(repbuf) - 1);218} else {219strncpy(repbuf, "You are ", sizeof(repbuf) - 1);220strncat(repbuf, cname, sizeof(repbuf) - 1 - strlen(repbuf));221strncat(repbuf, "\n", sizeof(repbuf) - 1 - strlen(repbuf));222free(cname);223}224xmitlen = htons(strlen(repbuf));225recv_data.length = strlen(repbuf);226recv_data.data = repbuf;227if ((retval = krb5_net_write(context, 0, (char *)&xmitlen,228sizeof(xmitlen))) < 0) {229syslog(LOG_ERR, "%m: while writing len to client");230exit(1);231}232if ((retval = krb5_net_write(context, 0, (char *)recv_data.data,233recv_data.length)) < 0) {234syslog(LOG_ERR, "%m: while writing data to client");235exit(1);236}237238krb5_free_ticket(context, ticket);239if(keytab)240krb5_kt_close(context, keytab);241krb5_free_principal(context, server);242krb5_auth_con_free(context, auth_context);243krb5_free_context(context);244exit(0);245}246247248