Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/appl/sample/sserver/sserver.c
34890 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* appl/sample/sserver/sserver.c */
3
/*
4
* Copyright 1990,1991 by the Massachusetts Institute of Technology.
5
* All Rights Reserved.
6
*
7
* Export of this software from the United States of America may
8
* require a specific license from the United States Government.
9
* It is the responsibility of any person or organization contemplating
10
* export to obtain such a license before exporting.
11
*
12
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13
* distribute this software and its documentation for any purpose and
14
* without fee is hereby granted, provided that the above copyright
15
* notice appear in all copies and that both that copyright notice and
16
* this permission notice appear in supporting documentation, and that
17
* the name of M.I.T. not be used in advertising or publicity pertaining
18
* to distribution of the software without specific, written prior
19
* permission. Furthermore if you modify this software you must label
20
* your software as modified software and not distribute it in such a
21
* fashion that it might be confused with the original M.I.T. software.
22
* M.I.T. makes no representations about the suitability of
23
* this software for any purpose. It is provided "as is" without express
24
* or implied warranty.
25
*/
26
27
/*
28
* Sample Kerberos v5 server.
29
*
30
* sample_server:
31
* A sample Kerberos server, which reads an AP_REQ from a TCP socket,
32
* decodes it, and writes back the results (in ASCII) to the client.
33
*
34
* Usage:
35
* sample_server servername
36
*
37
* file descriptor 0 (zero) should be a socket connected to the requesting
38
* client (this will be correct if this server is started by inetd).
39
*/
40
41
#include "k5-int.h"
42
#include "com_err.h"
43
44
#include <stdio.h>
45
#include <string.h>
46
#include <ctype.h>
47
#include <sys/types.h>
48
#include <sys/socket.h>
49
#include <netinet/in.h>
50
#include <netdb.h>
51
#include <syslog.h>
52
53
#ifdef HAVE_UNISTD_H
54
#include <unistd.h>
55
#endif
56
57
#include "../sample.h"
58
59
extern krb5_deltat krb5_clockskew;
60
61
#ifndef GETPEERNAME_ARG3_TYPE
62
#define GETPEERNAME_ARG3_TYPE int
63
#endif
64
65
static void
66
usage(char *name)
67
{
68
fprintf(stderr, "usage: %s [-p port] [-s service] [-S keytab]\n",
69
name);
70
}
71
72
int
73
main(int argc, char *argv[])
74
{
75
krb5_context context;
76
krb5_auth_context auth_context = NULL;
77
krb5_ticket * ticket;
78
struct sockaddr_in peername;
79
GETPEERNAME_ARG3_TYPE namelen = sizeof(peername);
80
int sock = -1; /* incoming connection fd */
81
krb5_data recv_data;
82
short xmitlen;
83
krb5_error_code retval;
84
krb5_principal server;
85
char repbuf[BUFSIZ];
86
char *cname;
87
char *service = SAMPLE_SERVICE;
88
short port = 0; /* If user specifies port */
89
extern int opterr, optind;
90
extern char * optarg;
91
int ch;
92
krb5_keytab keytab = NULL; /* Allow specification on command line */
93
char *progname;
94
int on = 1;
95
96
progname = *argv;
97
98
retval = krb5_init_context(&context);
99
if (retval) {
100
com_err(argv[0], retval, "while initializing krb5");
101
exit(1);
102
}
103
104
/* open a log connection */
105
openlog("sserver", 0, LOG_DAEMON);
106
107
/*
108
* Parse command line arguments
109
*
110
*/
111
opterr = 0;
112
while ((ch = getopt(argc, argv, "p:S:s:")) != -1) {
113
switch (ch) {
114
case 'p':
115
port = atoi(optarg);
116
break;
117
case 's':
118
service = optarg;
119
break;
120
case 'S':
121
if ((retval = krb5_kt_resolve(context, optarg, &keytab))) {
122
com_err(progname, retval,
123
"while resolving keytab file %s", optarg);
124
exit(2);
125
}
126
break;
127
128
case '?':
129
default:
130
usage(progname);
131
exit(1);
132
break;
133
}
134
}
135
136
argc -= optind;
137
argv += optind;
138
139
/* Backwards compatibility, allow port to be specified at end */
140
if (argc > 1) {
141
port = atoi(argv[1]);
142
}
143
144
retval = krb5_sname_to_principal(context, NULL, service,
145
KRB5_NT_SRV_HST, &server);
146
if (retval) {
147
syslog(LOG_ERR, "while generating service name (%s): %s",
148
service, error_message(retval));
149
exit(1);
150
}
151
152
/*
153
* If user specified a port, then listen on that port; otherwise,
154
* assume we've been started out of inetd.
155
*/
156
157
if (port) {
158
int acc;
159
struct sockaddr_in sockin;
160
161
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
162
syslog(LOG_ERR, "socket: %m");
163
exit(3);
164
}
165
/* Let the socket be reused right away */
166
(void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
167
sizeof(on));
168
169
sockin.sin_family = AF_INET;
170
sockin.sin_addr.s_addr = 0;
171
sockin.sin_port = htons(port);
172
if (bind(sock, (struct sockaddr *) &sockin, sizeof(sockin))) {
173
syslog(LOG_ERR, "bind: %m");
174
exit(3);
175
}
176
if (listen(sock, 1) == -1) {
177
syslog(LOG_ERR, "listen: %m");
178
exit(3);
179
}
180
181
printf("starting...\n");
182
fflush(stdout);
183
184
if ((acc = accept(sock, (struct sockaddr *)&peername, &namelen)) == -1){
185
syslog(LOG_ERR, "accept: %m");
186
exit(3);
187
}
188
dup2(acc, 0);
189
close(sock);
190
sock = 0;
191
} else {
192
/*
193
* To verify authenticity, we need to know the address of the
194
* client.
195
*/
196
if (getpeername(0, (struct sockaddr *)&peername, &namelen) < 0) {
197
syslog(LOG_ERR, "getpeername: %m");
198
exit(1);
199
}
200
sock = 0;
201
}
202
203
retval = krb5_recvauth(context, &auth_context, (krb5_pointer)&sock,
204
SAMPLE_VERSION, server,
205
0, /* no flags */
206
keytab, /* default keytab is NULL */
207
&ticket);
208
if (retval) {
209
syslog(LOG_ERR, "recvauth failed--%s", error_message(retval));
210
exit(1);
211
}
212
213
/* Get client name */
214
repbuf[sizeof(repbuf) - 1] = '\0';
215
retval = krb5_unparse_name(context, ticket->enc_part2->client, &cname);
216
if (retval){
217
syslog(LOG_ERR, "unparse failed: %s", error_message(retval));
218
strncpy(repbuf, "You are <unparse error>\n", sizeof(repbuf) - 1);
219
} else {
220
strncpy(repbuf, "You are ", sizeof(repbuf) - 1);
221
strncat(repbuf, cname, sizeof(repbuf) - 1 - strlen(repbuf));
222
strncat(repbuf, "\n", sizeof(repbuf) - 1 - strlen(repbuf));
223
free(cname);
224
}
225
xmitlen = htons(strlen(repbuf));
226
recv_data.length = strlen(repbuf);
227
recv_data.data = repbuf;
228
if ((retval = krb5_net_write(context, 0, (char *)&xmitlen,
229
sizeof(xmitlen))) < 0) {
230
syslog(LOG_ERR, "%m: while writing len to client");
231
exit(1);
232
}
233
if ((retval = krb5_net_write(context, 0, (char *)recv_data.data,
234
recv_data.length)) < 0) {
235
syslog(LOG_ERR, "%m: while writing data to client");
236
exit(1);
237
}
238
239
krb5_free_ticket(context, ticket);
240
if(keytab)
241
krb5_kt_close(context, keytab);
242
krb5_free_principal(context, server);
243
krb5_auth_con_free(context, auth_context);
244
krb5_free_context(context);
245
exit(0);
246
}
247
248