1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 #pragma ident "%Z%%M% %I% %E% SMI"
7
8 /*
9 * gssutil.c
10 *
11 * Utility routines for providing security related services to
12 * the FTP server. This code uses the GSSAPI (RFC 2743, 2744)
13 * to provide a generic security layer to the application. The
14 * security mechanism providing the actual security functions
15 * is abstracted from the application itself. In the case of the FTP
16 * server, the security mechanism is based on what the client chooses
17 * to use when it makes the secure connection. If the client's
18 * choice of GSS mechanism is not supported by the FTP server, the
19 * connection may be rejected or fall back to standard Unix/PAM
20 * authentication.
21 *
22 * This code is primarily intended to work with clients who choose
23 * the Kerberos V5 GSSAPI mechanism as their security service.
24 */
25
26 #include "config.h"
27
28 #if defined(USE_GSS)
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <ctype.h>
33 #include <stdlib.h>
34 #include <signal.h>
35 #include <pwd.h>
36
37 #include <netinet/in.h>
38 #include <netinet/in_systm.h>
39 #include <netinet/ip.h>
40
41 #include <errno.h>
42 #include <sys/param.h>
43 #include <netdb.h>
44 #ifdef HAVE_SYS_SYSLOG_H
45 #include <sys/syslog.h>
46 #endif
47
48 /* CSTYLED */
49 #if defined(HAVE_SYSLOG_H) || (!defined(AUTOCONF) && !defined(HAVE_SYS_SYSLOG_H))
50 #include <syslog.h>
51 #endif
52
53 #ifdef HAVE_SYSINFO
54 #include <sys/systeminfo.h>
55 #endif
56
57 #include <arpa/ftp.h>
58
59 #include "gssutil.h"
60 #include "proto.h"
61
62 static char *gss_services[] = { "ftp", "host", 0 };
63
64 gss_info_t gss_info = {
65 /* context */ GSS_C_NO_CONTEXT,
66 /* mechoid */ GSS_C_NULL_OID,
67 /* client */ NULL,
68 /* display_name */ NULL,
69 /* data_prot */ PROT_C,
70 /* ctrl_prot */ PROT_C,
71 /* authstate */ GSS_AUTH_NONE,
72 /* want_creds */ 0,
73 /* have_creds */ 0,
74 /* must_auth */ 0
75 };
76
77
78 extern char *cur_auth_type;
79 extern struct SOCKSTORAGE his_addr;
80 extern struct SOCKSTORAGE ctrl_addr;
81 extern int debug;
82
83 static char *radixN =
84 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
85
86 static char pad = '=';
87
88 #define DEF_GSSBUF_SIZE 2028
89 #define DECODELEN(l) (((3 * (l)) / 4) + 4)
90 #define ENCODELEN(l) (((4 * (l)) / 3) + 4)
91
92 typedef struct {
93 char *buf;
94 size_t alloc_len;
95 size_t len; /* max length of buffer */
96 size_t idx; /* offset to beginning of read/write data */
97 size_t clen; /* length of the remaining, decrypted data from client */
98 }bufrec;
99
100 static bufrec obr = {NULL, 0, 0, 0, 0};
101 static bufrec ibr = {NULL, 0, 0, 0, 0};
102
103 static int looping_write(int fd, const char *buf, size_t len);
104 static int looping_read(int fd, char *buf, size_t len);
105 static int radix_encode(unsigned char *inbuf, unsigned char *outbuf,
106 size_t len, int *outlen, int decode);
107 static char *radix_error(int e);
108 static void reply_gss_error(int code, OM_uint32 maj_stat,
109 OM_uint32 min_stat, gss_OID mechoid, char *s);
110 static void cleanup_bufrec(bufrec *brec);
111 static int alloc_bufrec(bufrec *brec, size_t newsz);
112 static int sec_putbuf(int fd, unsigned char *buf, int len);
113 static int sec_getbytes(int fd, char *buf, int nbytes);
114
115 /*
116 * Provide a routine so that ftpd can know the max amount to read
117 */
118 size_t
gss_getinbufsz(void)119 gss_getinbufsz(void) {
120 return (ibr.len);
121 }
122
123 /*
124 * gss_adjust_buflen
125 *
126 * Called when the protection method changes so we can adjust the
127 * "useable" length of our output buffer accordingly.
128 */
129 void
gss_adjust_buflen()130 gss_adjust_buflen()
131 {
132 OM_uint32 maj_stat, min_stat, mlen;
133
134 /*
135 * If we switched to CLEAR protection, we can use the entire buffer
136 */
137 if (gss_info.data_prot == PROT_C) {
138 obr.len = obr.alloc_len;
139 return;
140 }
141
142 /*
143 * Otherwise, determine the maximum size that will allow for
144 * the GSSAPI overhead to fit into the buffer size.
145 */
146 maj_stat = gss_wrap_size_limit(&min_stat, gss_info.context,
147 (gss_info.data_prot == PROT_P),
148 GSS_C_QOP_DEFAULT,
149 (OM_uint32)obr.alloc_len, &mlen);
150 if (maj_stat != GSS_S_COMPLETE) {
151 reply_gss_error(535, maj_stat, min_stat,
152 gss_info.mechoid,
153 "GSSAPI fudge determination");
154 return;
155 }
156 obr.len = mlen;
157
158 if (debug)
159 syslog(LOG_DEBUG, "GSSAPI alloc_len = %d len = %d",
160 obr.alloc_len, obr.len);
161 }
162
163 static int
looping_write(int fd,const char * buf,size_t len)164 looping_write(int fd, const char *buf, size_t len)
165 {
166 int cc;
167 register size_t wrlen = len;
168
169 do {
170 cc = write(fd, buf, wrlen);
171 if (cc < 0) {
172 if (errno == EINTR)
173 continue;
174 return (cc);
175 } else {
176 buf += cc;
177 wrlen -= cc;
178 }
179 } while (wrlen > 0);
180
181 return (len);
182 }
183
184 static int
looping_read(int fd,char * buf,size_t len)185 looping_read(int fd, char *buf, size_t len)
186 {
187 int cc;
188 size_t len2 = 0;
189
190 do {
191 cc = read(fd, buf, len);
192 if (cc < 0) {
193 if (errno == EINTR)
194 continue;
195 return (cc); /* errno is already set */
196 } else if (cc == 0) {
197 return (len2);
198 } else {
199 buf += cc;
200 len2 += cc;
201 len -= cc;
202 }
203 } while (len > 0);
204 return (len2);
205 }
206
207 static int
radix_encode(unsigned char * inbuf,unsigned char * outbuf,size_t buflen,int * outlen,int decode)208 radix_encode(unsigned char *inbuf, unsigned char *outbuf,
209 size_t buflen, int *outlen, int decode)
210 {
211 register int i, j, D;
212 char *p;
213 unsigned char c;
214
215 if (decode) {
216 for (i = 0, j = 0; (j < buflen) &&
217 inbuf[i] && inbuf[i] != pad; i++) {
218 if ((p = strchr(radixN, inbuf[i])) == NULL)
219 return (1);
220 D = p - radixN;
221 switch (i&3) {
222 case 0:
223 outbuf[j] = D <<2;
224 break;
225 case 1:
226 outbuf[j++] |= D >>4;
227 outbuf[j] = (D&15)<<4;
228 break;
229 case 2:
230 outbuf[j++] |= D >>2;
231 outbuf[j] = (D&3)<<6;
232 break;
233 case 3:
234 outbuf[j++] |= D;
235 }
236 }
237 if (j == buflen && (inbuf[i] && inbuf[i] != pad)) {
238 /* Oops, we ran out of space in the output buffer */
239 return (4);
240 }
241 switch (i&3) {
242 case 1:
243 return (3);
244 case 2: if (D&15)
245 return (3);
246 if (strcmp((char *)&inbuf[i], "=="))
247 return (2);
248 break;
249 case 3: if (D&3)
250 return (3);
251 if (strcmp((char *)&inbuf[i], "="))
252 return (2);
253 }
254 *outlen = j;
255 } else {
256 for (i = 0, j = 0; i < *outlen && j < buflen; i++)
257 switch (i%3) {
258 case 0:
259 outbuf[j++] = radixN[inbuf[i]>>2];
260 c = (inbuf[i]&3)<<4;
261 break;
262 case 1:
263 outbuf[j++] = radixN[c|inbuf[i]>>4];
264 c = (inbuf[i]&15)<<2;
265 break;
266 case 2:
267 outbuf[j++] = radixN[c|inbuf[i]>>6];
268 outbuf[j++] = radixN[inbuf[i]&63];
269 c = 0;
270 }
271 if (j == buflen && i < *outlen) {
272 /* output buffer is not big enough */
273 return (4);
274 }
275
276 if (i%3) outbuf[j++] = radixN[c];
277 switch (i%3) {
278 case 1: outbuf[j++] = pad;
279 case 2: outbuf[j++] = pad;
280 }
281 outbuf[*outlen = j] = '\0';
282 }
283 return (0);
284 }
285
286 static char *
radix_error(int e)287 radix_error(int e)
288 {
289 switch (e) {
290 case 0: return ("Success");
291 case 1: return ("Bad character in encoding");
292 case 2: return ("Encoding not properly padded");
293 case 3: return ("Decoded # of bits not a multiple of 8");
294 case 4: return ("Buffer size error");
295 default: return ("Unknown error");
296 }
297 }
298
299 static void
reply_gss_error(int code,OM_uint32 maj_stat,OM_uint32 min_stat,gss_OID mechoid,char * s)300 reply_gss_error(int code, OM_uint32 maj_stat,
301 OM_uint32 min_stat, gss_OID mechoid, char *s)
302 {
303 /* a lot of work just to report the error */
304 OM_uint32 gmaj_stat, gmin_stat;
305 gss_buffer_desc msg;
306 int msg_ctx;
307 msg_ctx = 0;
308
309 gmaj_stat = gss_display_status(&gmin_stat, maj_stat,
310 GSS_C_GSS_CODE,
311 mechoid,
312 (OM_uint32 *)&msg_ctx, &msg);
313 if (gmaj_stat == GSS_S_COMPLETE) {
314 lreply(code, "GSSAPI error major: %s",
315 (char *)msg.value);
316 (void) gss_release_buffer(&gmin_stat, &msg);
317 }
318
319 gmaj_stat = gss_display_status(&gmin_stat, min_stat,
320 GSS_C_MECH_CODE,
321 mechoid,
322 (OM_uint32 *)&msg_ctx, &msg);
323 if (gmaj_stat == GSS_S_COMPLETE) {
324 lreply(code, "GSSAPI error minor: %s", (char *)msg.value);
325 (void) gss_release_buffer(&gmin_stat, &msg);
326 }
327
328 reply(code, "GSSAPI error: %s", s);
329 }
330
331
332 static void
log_status(char * msg,OM_uint32 status_code,int status_type)333 log_status(char *msg,
334 OM_uint32 status_code,
335 int status_type)
336 {
337 OM_uint32 message_context;
338 gss_buffer_desc status_string;
339 OM_uint32 maj_status;
340 OM_uint32 min_status;
341
342 /* From RFC2744: */
343 message_context = 0;
344
345 do {
346 maj_status = gss_display_status(
347 &min_status,
348 status_code,
349 status_type,
350 GSS_C_NO_OID,
351 &message_context,
352 &status_string);
353
354 if (maj_status == GSS_S_COMPLETE) {
355 syslog(LOG_ERR,
356 "GSSAPI Error %s: %.*s\n",
357 msg ? msg : "<null>",
358 (int)status_string.length,
359 (char *)status_string.value);
360
361 (void) gss_release_buffer(&min_status,
362 &status_string);
363 } else {
364 syslog(LOG_ERR,
365 "log_status internal error: gss_display_status failed");
366 return;
367 }
368 } while (message_context != 0);
369
370 }
371
372 static void
log_gss_error(char * msg,OM_uint32 maj_stat,OM_uint32 min_stat)373 log_gss_error(char *msg,
374 OM_uint32 maj_stat,
375 OM_uint32 min_stat)
376 {
377 log_status(msg, maj_stat, GSS_C_GSS_CODE);
378 log_status(msg, min_stat, GSS_C_MECH_CODE);
379 }
380
381
382 static void
log_gss_info(int priority,char * luser,char * remprinc,gss_OID mechoid,char * s)383 log_gss_info(int priority,
384 char *luser,
385 char *remprinc,
386 gss_OID mechoid,
387 char *s)
388 {
389 const char *mechStr = __gss_oid_to_mech(mechoid);
390
391 syslog(priority,
392 "%s: local user=`%s', remote princ=`%s', mech=%s",
393 s ? s : "<null>",
394 luser ? luser : "<null>",
395 remprinc ? remprinc : "<unknown>",
396 mechStr ? mechStr : "<unknown>");
397 }
398
399 /*
400 * gss_user
401 *
402 * Handle USER command after AUTH GSSAPI
403 *
404 * Check if the remote user can login to the local system w/out a passwd.
405 * Use the Solaris (private) interface (__gss_userok) if possible, else do
406 * a basic GSS-API compare.
407 *
408 * return 0 == BAD
409 * 1 == OK
410 */
411 int
gss_user(struct passwd * user_pw)412 gss_user(struct passwd *user_pw)
413 {
414 int retval = 0;
415 OM_uint32 status, minor;
416
417 #ifdef SOLARIS_GSS_USEROK
418
419 int user_ok = 0;
420
421 if (debug)
422 log_gss_info(LOG_DEBUG,
423 user_pw->pw_name, gss_info.display_name,
424 gss_info.mechoid,
425 "gss_user: start (gss_userok)");
426
427 /* gss_auth_rules(5) */
428 status = __gss_userok(&minor, gss_info.client,
429 user_pw->pw_name, &user_ok);
430 if (status == GSS_S_COMPLETE) {
431 if (user_ok) {
432 retval = 1; /* remote user is a-ok */
433 }
434 }
435
436 #else /* SOLARIS_GSS_USEROK */
437
438 gss_name_t imported_name;
439 gss_name_t canon_name;
440 gss_buffer_desc gss_user;
441 OM_uint32 tmpMinor;
442 int match = 0;
443
444 if (debug)
445 log_gss_info(LOG_DEBUG,
446 user_pw->pw_name, gss_info.display_name,
447 gss_info.mechoid, "gss_user: start");
448
449 gss_user.value = user_pw->pw_name;
450 gss_user.length = strlen(gss_user.value);
451
452 status = gss_import_name(&minor,
453 &gss_user,
454 GSS_C_NT_USER_NAME,
455 &imported_name);
456 if (status != GSS_S_COMPLETE) {
457 goto out;
458 }
459
460 status = gss_canonicalize_name(&minor,
461 imported_name,
462 gss_info.mechoid,
463 &canon_name);
464 if (status != GSS_S_COMPLETE) {
465 (void) gss_release_name(&tmpMinor, &imported_name);
466 goto out;
467 }
468
469 status = gss_compare_name(&minor,
470 canon_name,
471 gss_info.client,
472 &match);
473 (void) gss_release_name(&tmpMinor, &canon_name);
474 (void) gss_release_name(&tmpMinor, &imported_name);
475 if (status == GSS_S_COMPLETE) {
476 if (match) {
477 retval = 1; /* remote user is a-ok */
478 }
479 }
480
481 out:
482
483 #endif /* SOLARIS_GSS_USEROK */
484
485 if (status != GSS_S_COMPLETE) {
486 log_gss_info(LOG_ERR, user_pw->pw_name,
487 gss_info.display_name, gss_info.mechoid,
488 "gss_user failed");
489 log_gss_error("gss_user failed", status, minor);
490 }
491
492 if (debug)
493 syslog(LOG_DEBUG, "gss_user: end: retval=%d", retval);
494
495 return (retval);
496 }
497
498
499 /*
500 * gss_adat
501 *
502 * Handle ADAT(Authentication Data) command data.
503 */
504 int
gss_adat(char * adatstr)505 gss_adat(char *adatstr)
506 {
507 int kerror, length;
508 int replied = 0;
509 int ret_flags;
510 gss_buffer_desc tok, out_tok;
511 gss_cred_id_t deleg_creds = NULL;
512 OM_uint32 accept_maj, accept_min;
513 OM_uint32 stat_maj, stat_min;
514 uchar_t *gout_buf;
515 size_t outlen;
516
517 length = strlen(adatstr);
518 outlen = DECODELEN(length);
519
520 gout_buf = (uchar_t *)malloc(outlen);
521 if (gout_buf == NULL) {
522 reply(501, "Couldn't decode ADAT, not enough memory");
523 syslog(LOG_ERR, "Couldn't decode ADAT, not enough memory");
524 return (0);
525 }
526
527 if ((kerror = radix_encode((unsigned char *)adatstr,
528 (unsigned char *)gout_buf,
529 outlen, &length, 1))) {
530 reply(501, "Couldn't decode ADAT(%s)",
531 radix_error(kerror));
532 syslog(LOG_ERR, "Couldn't decode ADAT(%s)",
533 radix_error(kerror));
534 return (0);
535 }
536 tok.value = gout_buf;
537 tok.length = length;
538
539 gss_info.context = GSS_C_NO_CONTEXT;
540
541 /*
542 * Call accept_sec_context w/GSS_C_NO_CREDENTIAL to request
543 * default cred and to not limit the service name to one name
544 * but rather accept what the clnt requests if service
545 * princ/keys are available.
546 */
547 if (debug)
548 syslog(LOG_DEBUG,
549 "gss_adat: accept_sec_context will try default cred");
550
551 out_tok.value = NULL;
552 out_tok.length = 0;
553
554 accept_maj = gss_accept_sec_context(&accept_min,
555 &gss_info.context,
556 GSS_C_NO_CREDENTIAL,
557 &tok, /* ADAT data */
558 GSS_C_NO_CHANNEL_BINDINGS,
559 &gss_info.client,
560 &gss_info.mechoid,
561 &out_tok, /* output_token */
562 (unsigned int *)&ret_flags,
563 NULL, /* ignore time_rec */
564 NULL); /* delegated creds */
565
566
567 if (debug) {
568 if (accept_maj == GSS_S_COMPLETE)
569 syslog(LOG_DEBUG,
570 "gss_adat: accept_maj = GSS_S_COMPLETE");
571 else if (accept_maj == GSS_S_CONTINUE_NEEDED)
572 syslog(LOG_DEBUG,
573 "gss_adat: accept_maj = GSS_S_CONTINUE_NEEDED");
574 }
575 free(gout_buf);
576
577 if (accept_maj != GSS_S_COMPLETE &&
578 accept_maj != GSS_S_CONTINUE_NEEDED) {
579 reply_gss_error(535, accept_maj, accept_min,
580 GSS_C_NO_OID, "accepting context");
581 syslog(LOG_ERR, "failed accepting context");
582 if ((ret_flags & GSS_C_DELEG_FLAG) &&
583 deleg_creds != NULL)
584 (void) gss_release_cred(&stat_min,
585 &deleg_creds);
586
587 (void) gss_release_buffer(&stat_min, &out_tok);
588 return (0);
589 }
590
591 if (debug)
592 syslog(LOG_DEBUG, "gss_adat: out_tok.length=%d",
593 out_tok.length);
594 if (out_tok.length) {
595 size_t buflen = ENCODELEN(out_tok.length);
596 uchar_t *gbuf = (uchar_t *)malloc(buflen);
597 if (gbuf == NULL) {
598 reply(535, "Couldn't encode ADAT reply, "
599 "not enough memory.");
600 syslog(LOG_ERR, "Couldn't encode ADAT reply, "
601 "not enough memory.");
602 (void) gss_release_buffer(&stat_min, &out_tok);
603 return (0);
604 }
605 if ((kerror = radix_encode(out_tok.value,
606 (unsigned char *)gbuf,
607 buflen, (int *)&out_tok.length,
608 0))) {
609 reply(535, "Couldn't encode ADAT reply(%s)",
610 radix_error(kerror));
611 syslog(LOG_ERR, "couldn't encode ADAT reply");
612 if ((ret_flags & GSS_C_DELEG_FLAG) &&
613 deleg_creds != NULL)
614 (void) gss_release_cred(&stat_min,
615 &deleg_creds);
616
617 (void) gss_release_buffer(&stat_min, &out_tok);
618 free(gbuf);
619 return (0);
620 }
621
622 if (accept_maj == GSS_S_COMPLETE) {
623 reply(235, "ADAT=%s", gbuf);
624 replied = 1;
625 } else {
626 /*
627 * If the server accepts the security data, and
628 * requires additional data, it should respond
629 * with reply code 335.
630 */
631 reply(335, "ADAT=%s", gbuf);
632 }
633 free(gbuf);
634 (void) gss_release_buffer(&stat_min, &out_tok);
635 }
636 if (accept_maj == GSS_S_COMPLETE) {
637 gss_buffer_desc namebuf;
638 gss_OID out_oid;
639
640 /* GSSAPI authentication succeeded */
641 gss_info.authstate = GSS_ADAT_DONE;
642 (void) alloc_bufrec(&obr, DEF_GSSBUF_SIZE);
643 (void) alloc_bufrec(&ibr, DEF_GSSBUF_SIZE);
644 /*
645 * RFC 2228 - "..., once a security data exchange completes
646 * successfully, if the security mechanism supports
647 * integrity, then integrity(via the MIC or ENC command,
648 * and 631 or 632 reply) must be used, ..."
649 */
650 gss_info.ctrl_prot = PROT_S;
651
652 stat_maj = gss_display_name(&stat_min, gss_info.client,
653 &namebuf, &out_oid);
654 if (stat_maj != GSS_S_COMPLETE) {
655 /*
656 * RFC 2228 -
657 * "If the server rejects the security data(if
658 * a checksum fails, for instance), it should
659 * respond with reply code 535."
660 */
661 reply_gss_error(535, stat_maj, stat_min,
662 gss_info.mechoid,
663 "extracting GSSAPI identity name");
664 syslog(LOG_ERR, "gssapi error extracting identity");
665 if ((ret_flags & GSS_C_DELEG_FLAG) &&
666 deleg_creds != NULL)
667 (void) gss_release_cred(&stat_min,
668 &deleg_creds);
669 return (0);
670 }
671 gss_info.display_name = (char *)namebuf.value;
672
673 if (ret_flags & GSS_C_DELEG_FLAG) {
674 gss_info.have_creds = 1;
675 if (deleg_creds != NULL)
676 (void) gss_release_cred(&stat_min,
677 &deleg_creds);
678 }
679
680 /*
681 * If the server accepts the security data, but does
682 * not require any additional data(i.e., the security
683 * data exchange has completed successfully), it must
684 * respond with reply code 235.
685 */
686 if (!replied) {
687 if ((ret_flags & GSS_C_DELEG_FLAG) &&
688 !gss_info.have_creds)
689 reply(235,
690 "GSSAPI Authentication succeeded, but "
691 "could not accept forwarded credentials");
692 else
693 reply(235, "GSSAPI Authentication succeeded");
694 }
695 return (1);
696 } else if (accept_maj == GSS_S_CONTINUE_NEEDED) {
697 /*
698 * If the server accepts the security data, and
699 * requires additional data, it should respond with
700 * reply code 335.
701 */
702 reply(335, "more data needed");
703 if ((ret_flags & GSS_C_DELEG_FLAG) &&
704 deleg_creds != NULL)
705 (void) gss_release_cred(&stat_min, &deleg_creds);
706 }
707
708 return (0);
709 }
710
711 /*
712 * cleanup_bufrec
713 *
714 * cleanup the secure buffers
715 */
716 static void
cleanup_bufrec(bufrec * brec)717 cleanup_bufrec(bufrec *brec)
718 {
719 if (brec->buf)
720 free(brec->buf);
721 brec->len = 0;
722 brec->clen = 0;
723 brec->idx = 0;
724 }
725
726 static int
alloc_bufrec(bufrec * brec,size_t newsz)727 alloc_bufrec(bufrec *brec, size_t newsz)
728 {
729 /*
730 * Try to allocate a buffer, if it fails,
731 * divide by 2 and try again.
732 */
733 cleanup_bufrec(brec);
734
735 while (newsz > 0 && !(brec->buf = malloc(newsz))) {
736 syslog(LOG_ERR,
737 "malloc bufrec(%d bytes) failed, trying %d",
738 newsz >>= 1);
739 }
740
741 if (brec->buf == NULL)
742 return (-1);
743
744 brec->alloc_len = newsz;
745 brec->len = newsz;
746 brec->clen = 0;
747 brec->idx = 0;
748 return (0);
749 }
750
751 /*
752 * Handle PBSZ command data, return value to caller.
753 * RFC 2228 says this is a 32 bit int, so limit max value here.
754 */
755 unsigned int
gss_setpbsz(char * pbszstr)756 gss_setpbsz(char *pbszstr)
757 {
758 unsigned int newsz = 0;
759 char *endp;
760 #define MAX_PBSZ 4294967295U
761
762 errno = 0;
763 newsz = (unsigned int)strtol(pbszstr, &endp, 10);
764 if (errno != 0 || newsz > MAX_PBSZ || *endp != '\0') {
765 reply(501, "Bad value for PBSZ: %s", pbszstr);
766 return (0);
767 }
768
769 if (newsz > ibr.len) {
770 if (alloc_bufrec(&obr, newsz) == -1) {
771 perror_reply(421, "Local resource failure: malloc");
772 dologout(1);
773 }
774 if (alloc_bufrec(&ibr, newsz) == -1) {
775 perror_reply(421, "Local resource failure: malloc");
776 dologout(1);
777 }
778 }
779 reply(200, "PBSZ =%lu", ibr.len);
780
781 return (ibr.len);
782 }
783
784 /*
785 * sec_putbuf
786 *
787 * Wrap the plaintext 'buf' data using gss_wrap and send
788 * it out.
789 *
790 * returns:
791 * bytes written (success)
792 * -1 on error(errno set)
793 * -2 on security error
794 */
795 static int
sec_putbuf(int fd,unsigned char * buf,int len)796 sec_putbuf(int fd, unsigned char *buf, int len)
797 {
798 unsigned long net_len;
799 int ret = 0;
800 gss_buffer_desc in_buf, out_buf;
801 OM_uint32 maj_stat, min_stat;
802 int conf_state;
803
804 in_buf.value = buf;
805 in_buf.length = len;
806 maj_stat = gss_wrap(&min_stat, gss_info.context,
807 (gss_info.data_prot == PROT_P),
808 GSS_C_QOP_DEFAULT,
809 &in_buf, &conf_state,
810 &out_buf);
811
812 if (maj_stat != GSS_S_COMPLETE) {
813 reply_gss_error(535, maj_stat, min_stat,
814 gss_info.mechoid,
815 gss_info.data_prot == PROT_P ?
816 "GSSAPI wrap failed":
817 "GSSAPI sign failed");
818 return (-2);
819 }
820
821 net_len = (unsigned long)htonl((unsigned long) out_buf.length);
822
823 if ((ret = looping_write(fd, (const char *)&net_len, 4)) != 4) {
824 syslog(LOG_ERR, "Error writing net_len(%d): %m", net_len);
825 ret = -1;
826 goto putbuf_done;
827 }
828
829 if ((ret = looping_write(fd, out_buf.value, out_buf.length)) !=
830 out_buf.length) {
831 syslog(LOG_ERR, "Error writing %d bytes: %m", out_buf.length);
832 ret = -1;
833 goto putbuf_done;
834 }
835 putbuf_done:
836
837 gss_release_buffer(&min_stat, &out_buf);
838 return (ret);
839 }
840
841 /*
842 * sec_write
843 *
844 * If GSSAPI security is established, encode the output
845 * and write it to the client. Else, just write it directly.
846 */
847 int
sec_write(int fd,char * buf,int len)848 sec_write(int fd, char *buf, int len)
849 {
850 int nbytes = 0;
851 if (gss_info.data_prot == PROT_C ||
852 !IS_GSSAUTH(cur_auth_type) ||
853 !(gss_info.authstate & GSS_ADAT_DONE))
854 nbytes = write(fd, buf, len);
855 else {
856 /*
857 * Fill up the buffer before actually encrypting
858 * and writing it out.
859 */
860 while ((obr.idx < obr.len) && (len > 0)) {
861 int n, ret;
862
863 /* how many bytes can we fit into the buffer? */
864 n = (len < (obr.len - obr.idx) ? len :
865 obr.len - obr.idx);
866 memcpy(obr.buf + obr.idx, buf, n);
867
868 obr.idx += n;
869
870 if (obr.idx >= obr.len) {
871 ret = sec_putbuf(fd, (unsigned char *)obr.buf,
872 obr.idx);
873 obr.idx = 0;
874 if (ret < 0)
875 return (ret);
876 }
877 len -= n;
878 nbytes += n;
879 }
880 }
881
882 return (nbytes);
883 }
884
885 /*
886 * CCC
887 *
888 * Clear Command Channel.
889 *
890 * We will understand this command but not allow it in a secure
891 * connection. It is very dangerous to allow someone to degrade
892 * the security of the command channel. See RFC2228 for more info.
893 */
894 void
ccc(void)895 ccc(void)
896 {
897 /*
898 * Once we have negotiated security successfully,
899 * do not allow the control channel to be downgraded.
900 * It should be at least SAFE if not PRIVATE.
901 */
902 if (IS_GSSAUTH(cur_auth_type) &&
903 (gss_info.authstate & GSS_ADAT_DONE) == GSS_ADAT_DONE)
904 reply(534, "Control channel may not be downgraded");
905 else {
906 gss_info.ctrl_prot = PROT_C;
907 reply(200, "CCC ok");
908 }
909 }
910
911 int
sec_putc(int c,FILE * stream)912 sec_putc(int c, FILE *stream)
913 {
914 int ret = 0;
915 /*
916 * If we are NOT protecting the data
917 * OR not using the GSSAPI authentication
918 * OR GSSAPI data is not yet completed, send
919 * plaintext.
920 */
921 if (gss_info.data_prot == PROT_C ||
922 !IS_GSSAUTH(cur_auth_type) ||
923 !(gss_info.authstate & GSS_ADAT_DONE))
924 return (putc(c, stream));
925
926 /*
927 * Add the latest byte to the current buffer
928 */
929 if (obr.idx < obr.len) {
930 obr.buf[obr.idx++] = (unsigned char)(c & 0xff);
931 }
932
933 if (obr.idx == obr.len) {
934 ret = sec_putbuf(fileno(stream), (uchar_t *)obr.buf, obr.idx);
935 if (ret >= 0)
936 ret = 0;
937 obr.idx = 0;
938 }
939
940 return ((ret == 0 ? c : ret));
941 }
942
943 int
sec_fprintf(FILE * stream,char * fmt,...)944 sec_fprintf(FILE *stream, char *fmt, ...)
945 {
946 int ret;
947 va_list ap;
948 va_start(ap, fmt);
949
950 if (gss_info.data_prot == PROT_C ||
951 !IS_GSSAUTH(cur_auth_type) ||
952 !(gss_info.authstate & GSS_ADAT_DONE)) {
953 ret = vfprintf(stream, fmt, ap);
954 } else {
955 (void) vsnprintf(obr.buf, obr.len, fmt, ap);
956 ret = sec_putbuf(fileno(stream), (unsigned char *)obr.buf,
957 strlen(obr.buf));
958 }
959 va_end(ap);
960 return (ret);
961 }
962
963 /*
964 * sec_fflush
965 *
966 * If GSSAPI protection is configured, write out whatever remains
967 * in the output buffer using the secure routines, otherwise
968 * just flush the stream.
969 */
970 int
sec_fflush(FILE * stream)971 sec_fflush(FILE *stream)
972 {
973 int ret = 0;
974 if (gss_info.data_prot == PROT_C ||
975 !IS_GSSAUTH(cur_auth_type) ||
976 !(gss_info.authstate & GSS_ADAT_DONE)) {
977 fflush(stream);
978 return (0);
979 }
980 if (obr.idx > 0) {
981 ret = sec_putbuf(fileno(stream),
982 (unsigned char *)obr.buf, obr.idx);
983 obr.idx = 0;
984 }
985
986 if (ret >= 0)
987 ret = sec_putbuf(fileno(stream), (unsigned char *)"", 0);
988 /*
989 * putbuf returns number of bytes or a negative value,
990 * but fflush must return 0 or -1, so adjust the return
991 * value so that a positive value is interpreted as success.
992 */
993 return (ret >= 0 ? 0 : ret);
994 }
995
996 /*
997 * sec_getbytes
998 *
999 * Read and decrypt from the secure data channel.
1000 *
1001 * Return:
1002 * > 0 == number of bytes available in gssbuf
1003 * EOF == End of file.
1004 * -2 == GSS error.
1005 *
1006 */
1007 static int
sec_getbytes(int fd,char * buf,int nbytes)1008 sec_getbytes(int fd, char *buf, int nbytes)
1009 {
1010 /*
1011 * Only read from the network if our current buffer
1012 * is all used up.
1013 */
1014 if (ibr.idx >= ibr.clen) {
1015 int kerror;
1016 int conf_state;
1017 unsigned int length;
1018 gss_buffer_desc xmit_buf, msg_buf;
1019 OM_uint32 maj_stat, min_stat;
1020
1021 if ((kerror = looping_read(fd, (char *)&length, 4)) != 4) {
1022 reply(535, "Couldn't read PROT buffer length: %d/%s",
1023 kerror,
1024 (kerror == -1) ? strerror(errno) : "premature EOF");
1025 return (-2);
1026 }
1027
1028 if ((length = (unsigned int)ntohl(length)) > ibr.len) {
1029 reply(535, "Length(%d) > PBSZ(%d)", length, ibr.len);
1030 return (-2);
1031 }
1032
1033 if (length > 0) {
1034 if ((kerror = looping_read(fd, ibr.buf, length)) !=
1035 length) {
1036 reply(535, "Couldn't read %u byte PROT buf: %s",
1037 length, (kerror == -1) ?
1038 strerror(errno) : "premature EOF");
1039 return (-2);
1040 }
1041
1042 xmit_buf.value = (char *)ibr.buf;
1043 xmit_buf.length = length;
1044
1045 conf_state = (gss_info.data_prot == PROT_P);
1046
1047 /* decrypt/verify the message */
1048 maj_stat = gss_unwrap(&min_stat, gss_info.context,
1049 &xmit_buf, &msg_buf, &conf_state, NULL);
1050 if (maj_stat != GSS_S_COMPLETE) {
1051 reply_gss_error(535, maj_stat, min_stat,
1052 gss_info.mechoid,
1053 (gss_info.data_prot == PROT_P)?
1054 "failed unwrapping ENC message":
1055 "failed unwrapping MIC message");
1056 return (-2);
1057 }
1058
1059 memcpy(ibr.buf, msg_buf.value, msg_buf.length);
1060 ibr.clen = msg_buf.length;
1061 ibr.idx = 0;
1062
1063 gss_release_buffer(&min_stat, &msg_buf);
1064 } else {
1065 ibr.idx = 0;
1066 ibr.clen = 0;
1067 return (EOF);
1068 }
1069 }
1070
1071 /*
1072 * If there are 'nbytes' of plain text available, use them, else
1073 * get whats available.
1074 */
1075 nbytes = (nbytes < (ibr.clen - ibr.idx) ? nbytes : ibr.clen - ibr.idx);
1076
1077 memcpy(buf, ibr.buf + ibr.idx, nbytes);
1078 ibr.idx += nbytes;
1079
1080 return ((nbytes == 0 ? EOF : nbytes));
1081 }
1082
1083 /*
1084 * Get a buffer of 'maxlen' bytes from the client.
1085 * If we are using GSSAPI protection, use the secure
1086 * input buffer.
1087 */
1088 int
sec_read(int fd,char * buf,int maxlen)1089 sec_read(int fd, char *buf, int maxlen)
1090 {
1091 int nbytes = 0;
1092
1093 if (gss_info.data_prot != PROT_C &&
1094 IS_GSSAUTH(cur_auth_type) &&
1095 (gss_info.authstate & GSS_ADAT_DONE)) {
1096 /* Get as much data as possible */
1097 nbytes = sec_getbytes(fd, buf, maxlen);
1098 if (nbytes == EOF)
1099 nbytes = 0;
1100 } else {
1101 nbytes = read(fd, buf, maxlen);
1102 }
1103 return (nbytes);
1104 }
1105
1106 /*
1107 * sec_getc
1108 *
1109 * Get a single character from the secure network buffer.
1110 */
1111 int
sec_getc(FILE * stream)1112 sec_getc(FILE *stream)
1113 {
1114 int nbytes;
1115 unsigned char c;
1116
1117 if (gss_info.data_prot != PROT_C &&
1118 IS_GSSAUTH(cur_auth_type) &&
1119 (gss_info.authstate & GSS_ADAT_DONE)) {
1120 nbytes = sec_getbytes(fileno(stream), (char *)&c, 1);
1121 if (nbytes > 0)
1122 nbytes = (int)c;
1123 return (nbytes);
1124 } else
1125 return (getc(stream));
1126 }
1127
1128 /*
1129 * sec_reply
1130 *
1131 * Securely encode a reply destined for the ftp client
1132 * depending on the GSSAPI settings.
1133 */
1134 int
sec_reply(char * buf,int bufsiz,int n)1135 sec_reply(char *buf, int bufsiz, int n)
1136 {
1137 char *out = NULL, *in = NULL;
1138 size_t inlen;
1139 gss_buffer_desc in_buf, out_buf;
1140 OM_uint32 maj_stat, min_stat;
1141 int conf_state, length, kerror;
1142 int ret = 0;
1143
1144 if (debug)
1145 syslog(LOG_DEBUG, "encoding %s", buf);
1146
1147 in_buf.value = buf;
1148 in_buf.length = strlen(buf) + 1;
1149 maj_stat = gss_wrap(&min_stat, gss_info.context,
1150 gss_info.ctrl_prot == PROT_P,
1151 GSS_C_QOP_DEFAULT,
1152 &in_buf, &conf_state,
1153 &out_buf);
1154 if (maj_stat != GSS_S_COMPLETE) {
1155 syslog(LOG_ERR, "gss_wrap %s did not complete",
1156 (gss_info.ctrl_prot == PROT_P) ? "ENC": "MIC");
1157 ret = -2;
1158 gss_release_buffer(&min_stat, &out_buf);
1159 goto end;
1160 } else if ((gss_info.ctrl_prot == PROT_P) && !conf_state) {
1161 syslog(LOG_ERR, "gss_wrap did not encrypt message");
1162 ret = -2;
1163 gss_release_buffer(&min_stat, &out_buf);
1164 goto end;
1165 } else {
1166 out = (char *)malloc(out_buf.length);
1167 if (out == NULL) {
1168 syslog(LOG_ERR, "Memory error allocating buffer");
1169 ret = -2;
1170 gss_release_buffer(&min_stat, &out_buf);
1171 goto end;
1172 }
1173 memcpy(out, out_buf.value, out_buf.length);
1174 length = out_buf.length;
1175 gss_release_buffer(&min_stat, &out_buf);
1176 ret = 0;
1177 }
1178 /*
1179 * Base64 encode the reply. encrypted "out" becomes
1180 * encoded "in" buffer.
1181 * Stick it all back in 'buf' for final output.
1182 */
1183 inlen = ENCODELEN(length);
1184 in = (char *)malloc(inlen);
1185 if (in == NULL) {
1186 syslog(LOG_ERR, "Memory error allocating buffer");
1187 ret = -2;
1188 goto end;
1189 }
1190 if ((kerror = radix_encode((unsigned char *)out,
1191 (unsigned char *)in, inlen,
1192 &length, 0))) {
1193 syslog(LOG_ERR, "Couldn't encode reply(%s)",
1194 radix_error(kerror));
1195 strncpy(buf, in, bufsiz-1);
1196 buf[bufsiz - 1] = '\0';
1197 } else {
1198 snprintf(buf, bufsiz, "%s%c%s",
1199 gss_info.ctrl_prot == PROT_P ? "632" : "631",
1200 n ? ' ' : '-', in);
1201 }
1202 end:
1203 if (in) free(in);
1204 if (out) free(out);
1205
1206 return (ret);
1207 }
1208
1209 /*
1210 * sec_decode_command
1211 *
1212 * If a command is received which is encoded(ENC, MIC, or CONF),
1213 * decode it here using GSSAPI.
1214 */
1215 char *
sec_decode_command(char * cmd)1216 sec_decode_command(char *cmd)
1217 {
1218 char *out = NULL, *cp;
1219 int len, mic, outlen;
1220 gss_buffer_desc xmit_buf, msg_buf;
1221 OM_uint32 maj_stat, min_stat;
1222 int conf_state;
1223 int kerror;
1224 char *cs;
1225 char *s = cmd;
1226
1227 if ((cs = strpbrk(s, " \r\n")))
1228 *cs++ = '\0';
1229 upper(s);
1230
1231 if ((mic = strcmp(s, "ENC")) != 0 && strcmp(s, "MIC") &&
1232 strcmp(s, "CONF")) {
1233 reply(533, "All commands must be protected.");
1234 syslog(LOG_ERR, "Unprotected command received %s", s);
1235 *s = '\0';
1236 return (s);
1237 }
1238
1239 if ((cp = strpbrk(cs, " \r\n")))
1240 *cp = '\0';
1241
1242 outlen = DECODELEN(strlen(cs));
1243
1244 out = (char *)malloc(outlen);
1245 if (out == NULL) {
1246 reply(501, "Cannot decode response - not enough memory");
1247 syslog(LOG_ERR, "Cannot decode response - not enough memory");
1248 *s = '\0';
1249 return (s);
1250 }
1251 len = strlen(cs);
1252 if ((kerror = radix_encode((unsigned char *)cs,
1253 (unsigned char *)out,
1254 outlen, &len, 1))) {
1255 reply(501, "Can't base 64 decode argument to %s command(%s)",
1256 mic ? "MIC" : "ENC", radix_error(kerror));
1257 *s = '\0';
1258 free(out);
1259 return (s);
1260 }
1261
1262 if (debug)
1263 syslog(LOG_DEBUG, "getline got %d from %s <%s >\n",
1264 len, cs, mic ? "MIC" : "ENC");
1265
1266 xmit_buf.value = out;
1267 xmit_buf.length = len;
1268
1269 /* decrypt the message */
1270 conf_state = !mic;
1271 maj_stat = gss_unwrap(&min_stat, gss_info.context, &xmit_buf,
1272 &msg_buf, &conf_state, NULL);
1273 if (maj_stat == GSS_S_CONTINUE_NEEDED) {
1274 if (debug) syslog(LOG_DEBUG, "%s-unwrap continued",
1275 mic ? "MIC" : "ENC");
1276 reply(535, "%s-unwrap continued, oops", mic ? "MIC" : "ENC");
1277 *s = 0;
1278 free(out);
1279 return (s);
1280 }
1281
1282 free(out);
1283 if (maj_stat != GSS_S_COMPLETE) {
1284 reply_gss_error(535, maj_stat, min_stat,
1285 gss_info.mechoid,
1286 mic ? "failed unwrapping MIC message":
1287 "failed unwrapping ENC message");
1288 *s = 0;
1289 return (s);
1290 }
1291
1292 memcpy(s, msg_buf.value, msg_buf.length);
1293 strcpy(s + msg_buf.length-(s[msg_buf.length-1] ? 0 : 1), "\r\n");
1294 gss_release_buffer(&min_stat, &msg_buf);
1295
1296 return (s);
1297 }
1298
1299 #endif /* defined(USE_GSS) */
1300