static int print_cred(krb5_context context, krb5_creds *cred) { char t1[128], t2[128], *str; krb5_error_code ret; krb5_timestamp sec; krb5_timeofday (context, &sec); if(cred->times.starttime) krb5_format_time(context, cred->times.starttime, t1, sizeof(t1), 1); else krb5_format_time(context, cred->times.authtime, t1, sizeof(t1), 1); if(cred->times.endtime > sec) krb5_format_time(context, cred->times.endtime, t2, sizeof(t2), 1); else strlcpy(t2, ">>>Expired<<<", sizeof(t2)); ret = krb5_unparse_name (context, cred->server, &str); if (ret) { lreply(500, "krb5_unparse_name: %d", ret); return 1; } lreply(200, "%-20s %-20s %s", t1, t2, str); free(str); return 0; }
void statfilecmd (const char *filename) { FILE *fin; int c; char line[LINE_MAX]; snprintf (line, sizeof (line), "/bin/ls -lgA %s", filename); fin = ftpd_popen (line, "r"); lreply (211, "status of %s:", filename); while ((c = getc (fin)) != EOF) { if (c == '\n') { if (ferror (stdout)) { perror_reply (421, "control connection"); ftpd_pclose (fin); dologout (1); } if (ferror (fin)) { perror_reply (551, filename); ftpd_pclose (fin); return; } putc ('\r', stdout); } putc (c, stdout); } ftpd_pclose (fin); reply (211, "End of Status"); }
static int klist5(void) { krb5_error_code ret; krb5_context context; krb5_ccache ccache; krb5_principal principal; int exit_status = 200; ret = krb5_init_context (&context); if (ret) { lreply(500, "krb5_init_context failed: %d", ret); return 500; } if (k5ccname) ret = krb5_cc_resolve(context, k5ccname, &ccache); else ret = krb5_cc_default (context, &ccache); if (ret) { lreply(500, "krb5_cc_default: %d", ret); return 500; } ret = krb5_cc_get_principal (context, ccache, &principal); if (ret) { if(ret == ENOENT) lreply(500, "No ticket file: %s", krb5_cc_get_name(context, ccache)); else lreply(500, "krb5_cc_get_principal: %d", ret); return 500; } exit_status = print_tickets (context, ccache, principal); ret = krb5_cc_close (context, ccache); if (ret) { lreply(500, "krb5_cc_close: %d", ret); exit_status = 500; } krb5_free_principal (context, principal); krb5_free_context (context); return exit_status; }
static int print_tickets (krb5_context context, krb5_ccache ccache, krb5_principal principal) { krb5_error_code ret; krb5_cc_cursor cursor; krb5_creds cred; char *str; ret = krb5_unparse_name (context, principal, &str); if (ret) { lreply(500, "krb5_unparse_name: %d", ret); return 500; } lreply(200, "%17s: %s:%s", "Credentials cache", krb5_cc_get_type(context, ccache), krb5_cc_get_name(context, ccache)); lreply(200, "%17s: %s", "Principal", str); free (str); ret = krb5_cc_start_seq_get (context, ccache, &cursor); if (ret) { lreply(500, "krb5_cc_start_seq_get: %d", ret); return 500; } lreply(200, " Issued Expires Principal"); while ((ret = krb5_cc_next_cred (context, ccache, &cursor, &cred)) == 0) { if (print_cred(context, &cred)) return 500; krb5_free_cred_contents (context, &cred); } if (ret != KRB5_CC_END) { lreply(500, "krb5_cc_get_next: %d", ret); return 500; } ret = krb5_cc_end_seq_get (context, ccache, &cursor); if (ret) { lreply(500, "krb5_cc_end_seq_get: %d", ret); return 500; } return 200; }
int display_file (const char *name, int code) { char *cp, line[LINE_MAX]; FILE *fp = fopen (name, "r"); if (fp != NULL) { while (fgets (line, sizeof(line), fp) != NULL) { cp = strchr (line, '\n'); if (cp != NULL) *cp = '\0'; lreply (code, "%s", line); } (void) fflush (stdout); (void) fclose (fp); return 0; } return errno; }
static void complete_login (struct credentials *pcred) { if (setegid ((gid_t) pcred->gid) < 0) { reply (550, "Can't set gid."); return; } #ifdef HAVE_INITGROUPS initgroups (pcred->name, pcred->gid); #endif /* open wtmp before chroot */ snprintf (ttyline, sizeof (ttyline), "ftp%d", getpid ()); logwtmp_keep_open (ttyline, pcred->name, pcred->remotehost); if (pcred->guest) { /* We MUST do a chdir () after the chroot. Otherwise the old current directory will be accessible as "." outside the new root! */ if (chroot (pcred->rootdir) < 0 || chdir (pcred->homedir) < 0) { reply (550, "Can't set guest privileges."); goto bad; } } else if (pcred->dochroot) { if (chroot (pcred->rootdir) < 0 || chdir (pcred->homedir) < 0) { reply (550, "Can't change root."); goto bad; } setenv ("HOME", pcred->homedir, 1); } else if (chdir (pcred->rootdir) < 0) { if (chdir ("/") < 0) { reply (530, "User %s: can't change directory to %s.", pcred->name, pcred->homedir); goto bad; } else lreply (230, "No directory! Logging in with home=/"); } if (seteuid ((uid_t) pcred->uid) < 0) { reply (550, "Can't set uid."); goto bad; } /* Display a login message, if it exists. N.B. reply(230,) must follow the message. */ display_file (PATH_FTPLOGINMESG, 230); if (pcred->guest) { reply (230, "Guest login ok, access restrictions apply."); #ifdef HAVE_SETPROCTITLE snprintf (proctitle, sizeof (proctitle), "%s: anonymous", pcred->remotehost); setproctitle ("%s", proctitle); #endif /* HAVE_SETPROCTITLE */ if (logging) syslog (LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s", pcred->remotehost); } else { reply (230, "User %s logged in.", pcred->name); #ifdef HAVE_SETPROCTITLE snprintf (proctitle, sizeof (proctitle), "%s: %s", pcred->remotehost, pcred->name); setproctitle ("%s", proctitle); #endif /* HAVE_SETPROCTITLE */ if (logging) syslog (LOG_INFO, "FTP LOGIN FROM %s as %s", pcred->remotehost, pcred->name); } umask (defumask); return; bad: /* Forget all about it... */ end_login (pcred); }
void statcmd (void) { struct sockaddr_in *sin; u_char *a, *p; lreply (211, "%s FTP server status:", hostname); if (!no_version) printf (" ftpd (%s) %s\r\n", PACKAGE_NAME, PACKAGE_VERSION); printf (" Connected to %s", cred.remotehost); if (!isdigit (cred.remotehost[0])) printf (" (%s)", inet_ntoa (his_addr.sin_addr)); printf ("\r\n"); if (cred.logged_in) { if (cred.guest) printf (" Logged in anonymously\r\n"); else printf (" Logged in as %s\r\n", cred.name); } else if (askpasswd) printf (" Waiting for password\r\n"); else printf (" Waiting for user name\r\n"); printf (" TYPE: %s", typenames[type]); if (type == TYPE_A || type == TYPE_E) printf (", FORM: %s", formnames[form]); if (type == TYPE_L) #ifdef CHAR_BIT printf (" %d", CHAR_BIT); #else # if NBBY == 8 printf (" %d", NBBY); # else printf (" %d", bytesize); /* need definition! */ # endif #endif printf ("; STRUcture: %s; transfer MODE: %s\r\n", strunames[stru], modenames[stru_mode]); if (data != -1) printf (" Data connection open\r\n"); else if (pdata != -1) { printf (" in Passive mode"); sin = &pasv_addr; goto printaddr; } else if (usedefault == 0) { printf (" PORT"); sin = &data_dest; printaddr: a = (u_char *) & sin->sin_addr; p = (u_char *) & sin->sin_port; #define UC(b) (((int) b) & 0xff) printf (" (%d,%d,%d,%d,%d,%d)\r\n", UC (a[0]), UC (a[1]), UC (a[2]), UC (a[3]), UC (p[0]), UC (p[1])); #undef UC } else printf (" No data connection\r\n"); reply (211, "End of status"); }
/* Transfer data from peer to "outstr" using the appropriate encapulation of the data subject to Mode, Structure, and Type. N.B.: Form isn't handled. */ static int receive_data (FILE * instr, FILE * outstr) { int c; int cnt, bare_lfs = 0; char buf[BUFSIZ]; transflag++; if (setjmp (urgcatch)) { transflag = 0; return -1; } switch (type) { case TYPE_I: case TYPE_L: while ((cnt = read (fileno (instr), buf, sizeof (buf))) > 0) { if (write (fileno (outstr), buf, cnt) != cnt) goto file_err; byte_count += cnt; } if (cnt < 0) goto data_err; transflag = 0; return 0; case TYPE_E: reply (553, "TYPE E not implemented."); transflag = 0; return -1; case TYPE_A: while ((c = getc (instr)) != EOF) { byte_count++; if (c == '\n') bare_lfs++; while (c == '\r') { if (ferror (outstr)) goto data_err; c = getc (instr); if (c != '\n') { putc ('\r', outstr); if (c == '\0' || c == EOF) goto contin2; } } putc (c, outstr); contin2:; } fflush (outstr); if (ferror (instr)) goto data_err; if (ferror (outstr)) goto file_err; transflag = 0; if (bare_lfs) { lreply (226, "WARNING! %d bare linefeeds received in ASCII mode", bare_lfs); printf (" File may not have transferred correctly.\r\n"); } return (0); default: reply (550, "Unimplemented TYPE %d in receive_data", type); transflag = 0; return -1; } data_err: transflag = 0; perror_reply (426, "Data Connection"); return -1; file_err: transflag = 0; perror_reply (452, "Error writing file"); return -1; }