Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/appl/gss-sample/gss-misc.c
34907 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/*
3
* Copyright 1994 by OpenVision Technologies, Inc.
4
*
5
* Permission to use, copy, modify, distribute, and sell this software
6
* and its documentation for any purpose is hereby granted without fee,
7
* provided that the above copyright notice appears in all copies and
8
* that both that copyright notice and this permission notice appear in
9
* supporting documentation, and that the name of OpenVision not be used
10
* in advertising or publicity pertaining to distribution of the software
11
* without specific, written prior permission. OpenVision makes no
12
* representations about the suitability of this software for any
13
* purpose. It is provided "as is" without express or implied warranty.
14
*
15
* OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17
* EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21
* PERFORMANCE OF THIS SOFTWARE.
22
*/
23
/*
24
* Copyright (C) 2003, 2004 by the Massachusetts Institute of Technology.
25
* All rights reserved.
26
*
27
* Export of this software from the United States of America may
28
* require a specific license from the United States Government.
29
* It is the responsibility of any person or organization contemplating
30
* export to obtain such a license before exporting.
31
*
32
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
33
* distribute this software and its documentation for any purpose and
34
* without fee is hereby granted, provided that the above copyright
35
* notice appear in all copies and that both that copyright notice and
36
* this permission notice appear in supporting documentation, and that
37
* the name of M.I.T. not be used in advertising or publicity pertaining
38
* to distribution of the software without specific, written prior
39
* permission. Furthermore if you modify this software you must label
40
* your software as modified software and not distribute it in such a
41
* fashion that it might be confused with the original M.I.T. software.
42
* M.I.T. makes no representations about the suitability of
43
* this software for any purpose. It is provided "as is" without express
44
* or implied warranty.
45
*/
46
47
#include <autoconf.h>
48
49
#include <stdio.h>
50
#ifdef _WIN32
51
#include <windows.h>
52
#include <winsock.h>
53
#else
54
#include <sys/types.h>
55
#include <netinet/in.h>
56
#include <sys/socket.h>
57
#endif
58
#include <errno.h>
59
60
#ifdef HAVE_UNISTD_H
61
#include <unistd.h>
62
#endif
63
#include <string.h>
64
65
/* need struct timeval */
66
#ifdef HAVE_SYS_TIME_H
67
#include <sys/time.h>
68
#else
69
#include <time.h>
70
#endif
71
72
#include <gssapi/gssapi_generic.h>
73
#include "gss-misc.h"
74
75
#ifdef HAVE_STDLIB_H
76
#include <stdlib.h>
77
#else
78
extern char *malloc();
79
#endif
80
81
FILE *display_file;
82
83
gss_buffer_desc empty_token_buf = { 0, (void *) "" };
84
gss_buffer_t empty_token = &empty_token_buf;
85
86
static void display_status_1(char *m, OM_uint32 code, int type);
87
88
static int
89
write_all(int fildes, const void *data, unsigned int nbyte)
90
{
91
int ret;
92
const char *ptr, *buf = data;
93
94
for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) {
95
ret = send(fildes, ptr, nbyte, 0);
96
if (ret < 0) {
97
if (errno == EINTR)
98
continue;
99
return (ret);
100
} else if (ret == 0) {
101
return (ptr - buf);
102
}
103
}
104
105
return (ptr - buf);
106
}
107
108
static int
109
read_all(int fildes, void *data, unsigned int nbyte)
110
{
111
int ret;
112
char *ptr, *buf = data;
113
fd_set rfds;
114
struct timeval tv;
115
116
FD_ZERO(&rfds);
117
FD_SET(fildes, &rfds);
118
tv.tv_sec = 300;
119
tv.tv_usec = 0;
120
121
for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) {
122
if (select(FD_SETSIZE, &rfds, NULL, NULL, &tv) <= 0
123
|| !FD_ISSET(fildes, &rfds))
124
return (ptr - buf);
125
ret = recv(fildes, ptr, nbyte, 0);
126
if (ret < 0) {
127
if (errno == EINTR)
128
continue;
129
return (ret);
130
} else if (ret == 0) {
131
return (ptr - buf);
132
}
133
}
134
135
return (ptr - buf);
136
}
137
138
/*
139
* Function: send_token
140
*
141
* Purpose: Writes a token to a file descriptor.
142
*
143
* Arguments:
144
*
145
* s (r) an open file descriptor
146
* flags (r) the flags to write
147
* tok (r) the token to write
148
*
149
* Returns: 0 on success, -1 on failure
150
*
151
* Effects:
152
*
153
* If the flags are non-null, send_token writes the token flags (a
154
* single byte, even though they're passed in in an integer). Next,
155
* the token length (as a network long) and then the token data are
156
* written to the file descriptor s. It returns 0 on success, and -1
157
* if an error occurs or if it could not write all the data.
158
*/
159
int
160
send_token(int s, int flags, gss_buffer_t tok)
161
{
162
int ret;
163
unsigned char char_flags = (unsigned char) flags;
164
unsigned char lenbuf[4];
165
166
if (char_flags) {
167
ret = write_all(s, (char *) &char_flags, 1);
168
if (ret != 1) {
169
perror("sending token flags");
170
return -1;
171
}
172
}
173
if (tok->length > 0xffffffffUL)
174
abort();
175
lenbuf[0] = (tok->length >> 24) & 0xff;
176
lenbuf[1] = (tok->length >> 16) & 0xff;
177
lenbuf[2] = (tok->length >> 8) & 0xff;
178
lenbuf[3] = tok->length & 0xff;
179
180
ret = write_all(s, lenbuf, 4);
181
if (ret < 0) {
182
perror("sending token length");
183
return -1;
184
} else if (ret != 4) {
185
if (display_file)
186
fprintf(display_file,
187
"sending token length: %d of %d bytes written\n", ret, 4);
188
return -1;
189
}
190
191
ret = write_all(s, tok->value, tok->length);
192
if (ret < 0) {
193
perror("sending token data");
194
return -1;
195
} else if ((size_t)ret != tok->length) {
196
if (display_file)
197
fprintf(display_file,
198
"sending token data: %d of %d bytes written\n",
199
ret, (int) tok->length);
200
return -1;
201
}
202
203
return 0;
204
}
205
206
/*
207
* Function: recv_token
208
*
209
* Purpose: Reads a token from a file descriptor.
210
*
211
* Arguments:
212
*
213
* s (r) an open file descriptor
214
* flags (w) the read flags
215
* tok (w) the read token
216
*
217
* Returns: 0 on success, -1 on failure
218
*
219
* Effects:
220
*
221
* recv_token reads the token flags (a single byte, even though
222
* they're stored into an integer, then reads the token length (as a
223
* network long), allocates memory to hold the data, and then reads
224
* the token data from the file descriptor s. It blocks to read the
225
* length and data, if necessary. On a successful return, the token
226
* should be freed with gss_release_buffer. It returns 0 on success,
227
* and -1 if an error occurs or if it could not read all the data.
228
*/
229
int
230
recv_token(int s, int *flags, gss_buffer_t tok)
231
{
232
int ret;
233
unsigned char char_flags;
234
unsigned char lenbuf[4];
235
236
ret = read_all(s, (char *) &char_flags, 1);
237
if (ret < 0) {
238
perror("reading token flags");
239
return -1;
240
} else if (!ret) {
241
if (display_file)
242
fputs("reading token flags: 0 bytes read\n", display_file);
243
return -1;
244
} else {
245
*flags = (int) char_flags;
246
}
247
248
if (char_flags == 0) {
249
lenbuf[0] = 0;
250
ret = read_all(s, &lenbuf[1], 3);
251
if (ret < 0) {
252
perror("reading token length");
253
return -1;
254
} else if (ret != 3) {
255
if (display_file)
256
fprintf(display_file,
257
"reading token length: %d of %d bytes read\n", ret, 3);
258
return -1;
259
}
260
} else {
261
ret = read_all(s, lenbuf, 4);
262
if (ret < 0) {
263
perror("reading token length");
264
return -1;
265
} else if (ret != 4) {
266
if (display_file)
267
fprintf(display_file,
268
"reading token length: %d of %d bytes read\n", ret, 4);
269
return -1;
270
}
271
}
272
273
tok->length = ((lenbuf[0] << 24)
274
| (lenbuf[1] << 16)
275
| (lenbuf[2] << 8)
276
| lenbuf[3]);
277
tok->value = (char *) malloc(tok->length ? tok->length : 1);
278
if (tok->length && tok->value == NULL) {
279
if (display_file)
280
fprintf(display_file, "Out of memory allocating token data\n");
281
return -1;
282
}
283
284
ret = read_all(s, (char *) tok->value, tok->length);
285
if (ret < 0) {
286
perror("reading token data");
287
free(tok->value);
288
return -1;
289
} else if ((size_t)ret != tok->length) {
290
fprintf(stderr, "sending token data: %d of %d bytes written\n",
291
ret, (int) tok->length);
292
free(tok->value);
293
return -1;
294
}
295
296
return 0;
297
}
298
299
static void
300
display_status_1(char *m, OM_uint32 code, int type)
301
{
302
OM_uint32 min_stat;
303
gss_buffer_desc msg;
304
OM_uint32 msg_ctx;
305
306
msg_ctx = 0;
307
while (1) {
308
(void) gss_display_status(&min_stat, code, type, GSS_C_NULL_OID,
309
&msg_ctx, &msg);
310
if (display_file)
311
fprintf(display_file, "GSS-API error %s: %s\n", m,
312
(char *) msg.value);
313
(void) gss_release_buffer(&min_stat, &msg);
314
315
if (!msg_ctx)
316
break;
317
}
318
}
319
320
/*
321
* Function: display_status
322
*
323
* Purpose: displays GSS-API messages
324
*
325
* Arguments:
326
*
327
* msg a string to be displayed with the message
328
* maj_stat the GSS-API major status code
329
* min_stat the GSS-API minor status code
330
*
331
* Effects:
332
*
333
* The GSS-API messages associated with maj_stat and min_stat are
334
* displayed on stderr, each preceded by "GSS-API error <msg>: " and
335
* followed by a newline.
336
*/
337
void
338
display_status(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat)
339
{
340
display_status_1(msg, maj_stat, GSS_C_GSS_CODE);
341
display_status_1(msg, min_stat, GSS_C_MECH_CODE);
342
}
343
344
/*
345
* Function: display_ctx_flags
346
*
347
* Purpose: displays the flags returned by context initiation in
348
* a human-readable form
349
*
350
* Arguments:
351
*
352
* int ret_flags
353
*
354
* Effects:
355
*
356
* Strings corresponding to the context flags are printed on
357
* stdout, preceded by "context flag: " and followed by a newline
358
*/
359
360
void
361
display_ctx_flags(OM_uint32 flags)
362
{
363
if (flags & GSS_C_DELEG_FLAG)
364
fprintf(display_file, "context flag: GSS_C_DELEG_FLAG\n");
365
if (flags & GSS_C_MUTUAL_FLAG)
366
fprintf(display_file, "context flag: GSS_C_MUTUAL_FLAG\n");
367
if (flags & GSS_C_REPLAY_FLAG)
368
fprintf(display_file, "context flag: GSS_C_REPLAY_FLAG\n");
369
if (flags & GSS_C_SEQUENCE_FLAG)
370
fprintf(display_file, "context flag: GSS_C_SEQUENCE_FLAG\n");
371
if (flags & GSS_C_CONF_FLAG)
372
fprintf(display_file, "context flag: GSS_C_CONF_FLAG \n");
373
if (flags & GSS_C_INTEG_FLAG)
374
fprintf(display_file, "context flag: GSS_C_INTEG_FLAG \n");
375
}
376
377
void
378
print_token(gss_buffer_t tok)
379
{
380
unsigned int i;
381
unsigned char *p = tok->value;
382
383
if (!display_file)
384
return;
385
for (i = 0; i < tok->length; i++, p++) {
386
fprintf(display_file, "%02x ", *p);
387
if ((i % 16) == 15) {
388
fprintf(display_file, "\n");
389
}
390
}
391
fprintf(display_file, "\n");
392
fflush(display_file);
393
}
394
395
#ifdef _WIN32
396
#include <sys\timeb.h>
397
#include <time.h>
398
399
int
400
gettimeofday(struct timeval *tv, void *ignore_tz)
401
{
402
struct _timeb tb;
403
_tzset();
404
_ftime(&tb);
405
if (tv) {
406
tv->tv_sec = tb.time;
407
tv->tv_usec = tb.millitm * 1000;
408
}
409
return 0;
410
}
411
#endif /* _WIN32 */
412
413