/* authentication, server side */ int get_auth (int infd, krb5_context *ctx, krb5_auth_context *actx, krb5_keyblock **key, const char **err_msg, int *protoversion, int *cksumtype, char **cksum, size_t *cksumlen, char *srvname) { char *out; size_t outlen; char *buf; int buflen; int len; int rc; int error; /* KERBEROS 5 SENDAUTH MESSAGE */ char krb5sendauth[] = "KRB5_SENDAUTH_V1.0"; /* PROTOCOL VERSION */ char krb5kcmd1[] = "KCMDV0.1"; char krb5kcmd2[] = "KCMDV0.2"; char *servername, *server = NULL, *realm = NULL; *err_msg = NULL; /* Get key for the server. */ # if 0 /* * XXX: Taken straight from the version for libshishi. * XXX: No adaptions yet. */ rc = shishi_init_server (handle); if (rc != SHISHI_OK) return rc; if (srvname && *srvname) { rc = shishi_parse_name (*handle, srvname, &server, &realm); if (rc != SHISHI_OK) { *err_msg = shishi_strerror (rc); return rc; } } if (server && *server) { char *p; servername = malloc (sizeof (SERVICE) + strlen (server) + 2); if (!servername) { *err_msg = "Not enough memory"; return SHISHI_TOO_SMALL_BUFFER; } p = strchr (server, '/'); if (p && (p != server)) sprintf (servername, "%s", server); /* Non-empty prefix. */ else sprintf (servername, "%s/%s", SERVICE, server + (p ? 1 : 0)); /* Remove initial slash. */ } else servername = shishi_server_for_local_service (*handle, SERVICE); if (realm && *realm) shishi_realm_default_set (*handle, realm); free (server); free (realm); /* Enable use of `~/.k5login'. */ if (shishi_check_version ("1.0.2")) /* Faulty in version 1.0.1. */ { rc = shishi_cfg_authorizationtype_set (*handle, "k5login basic"); if (rc != SHISHI_OK) { *err_msg = shishi_error (*handle); return rc; } } key = shishi_hostkeys_for_serverrealm (*handle, servername, shishi_realm_default (*handle)); free (servername); if (!key) { *err_msg = shishi_error (*handle); return SHISHI_INVALID_KEY; } /* Read Kerberos 5 sendauth message */ rc = read (infd, &len, sizeof (int)); if (rc != sizeof (int)) { *err_msg = "Error reading message size"; return SHISHI_IO_ERROR; } buflen = ntohl (len); buf = malloc (buflen); if (!buf) { *err_msg = "Not enough memory"; return SHISHI_TOO_SMALL_BUFFER; } rc = read (infd, buf, buflen); if (rc != buflen) { *err_msg = "Error reading authentication message"; return SHISHI_IO_ERROR; } len = strlen (krb5sendauth); rc = strncmp (buf, krb5sendauth, buflen >= len ? len : buflen); if (rc) { *err_msg = "Invalid authentication type"; /* Authentication type is wrong. */ write (infd, "\001", 1); return SHISHI_VERIFY_FAILED; } free (buf); /* Read protocol version */ rc = read (infd, &len, sizeof (int)); if (rc != sizeof (int)) { *err_msg = "Error reading protocol message size"; return SHISHI_IO_ERROR; } buflen = ntohl (len); buf = malloc (buflen); if (!buf) { *err_msg = "Not enough memory"; return SHISHI_TOO_SMALL_BUFFER; } rc = read (infd, buf, buflen); if (rc != buflen) { *err_msg = "Error reading protocol message"; return SHISHI_IO_ERROR; } len = strlen (krb5kcmd1); rc = strncmp (buf, krb5kcmd1, buflen >= len ? len : buflen); if (rc) { len = strlen (krb5kcmd2); rc = strncmp (buf, krb5kcmd2, buflen >= len ? len : buflen); if (rc) { *err_msg = "Protocol version not supported"; /* Protocol version is wrong. */ write (infd, "\002", 1); return SHISHI_VERIFY_FAILED; } *protoversion = 2; } else *protoversion = 1; free (buf); /* Authentication type is ok */ write (infd, "\0", 1); /* Read Authentication request from client */ rc = read (infd, &len, sizeof (int)); if (rc != sizeof (int)) { *err_msg = "Error reading authentication request size"; return SHISHI_IO_ERROR; } buflen = ntohl (len); buf = malloc (buflen); if (!buf) { *err_msg = "Not enough memory"; return SHISHI_TOO_SMALL_BUFFER; } rc = read (infd, buf, buflen); if (rc != buflen) { *err_msg = "Error reading authentication request"; return SHISHI_IO_ERROR; } /* Create Authentication context */ rc = shishi_ap_nosubkey (*handle, ap); if (rc != SHISHI_OK) return rc; /* Store request in context */ rc = shishi_ap_req_der_set (*ap, buf, buflen); if (rc != SHISHI_OK) return rc; free (buf); /* Process authentication request */ rc = shishi_ap_req_process (*ap, key); if (rc != SHISHI_OK) return rc; # ifdef ENCRYPTION /* extract subkey if present from ap exchange for secure connection */ if (*protoversion == 2) { *enckey = NULL; shishi_authenticator_get_subkey (*handle, shishi_ap_authenticator (*ap), enckey); } # endif /* Get authenticator checksum */ rc = shishi_authenticator_cksum (*handle, shishi_ap_authenticator (*ap), cksumtype, cksum, cksumlen); if (rc != SHISHI_OK) return rc; /* User is authenticated. */ error = 0; write (infd, &error, sizeof (int)); /* Authenticate ourself to client, if requested. */ if (shishi_apreq_mutual_required_p (*handle, shishi_ap_req (*ap))) { int len; rc = shishi_ap_rep_der (*ap, &out, &outlen); if (rc != SHISHI_OK) return rc; len = outlen; len = htonl (len); rc = write (infd, &len, sizeof (len)); if (rc != sizeof (int)) { *err_msg = "Error sending AP-REP"; free (out); return SHISHI_IO_ERROR; } rc = write (infd, out, ntohl (len)); if (rc != (int) ntohl (len)) { *err_msg = "Error sending AP-REP"; free (out); return SHISHI_IO_ERROR; } free (out); /* We are authenticated to client */ } # ifdef ENCRYPTION if (*protoversion == 1) { Shishi_tkt *tkt; tkt = shishi_ap_tkt (*ap); if (tkt == NULL) { *err_msg = "Could not get tkt from AP-REQ"; return SHISHI_INVALID_TICKET; } rc = shishi_encticketpart_get_key (*handle, shishi_tkt_encticketpart (tkt), enckey); if (rc != SHISHI_OK) return rc; } # endif /* ENCRYPTION */ return 0; # else return -1; # endif }
int main (int argc, char *argv[]) { struct gengetopt_args_info args; time_t starttime, endtime, renew_till; Shishi *sh; int rc; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); set_program_name (argv[0]); if (cmdline_parser (argc, argv, &args) != 0) usage (EXIT_FAILURE); if (args.version_given) { version_etc (stdout, "shishi", PACKAGE_NAME, VERSION, "Simon Josefsson", (char *) NULL); return EXIT_SUCCESS; } if (args.inputs_num > 2 || args.destroy_given + args.list_given + args.renew_given > 1) { error (0, 0, _("too many arguments")); usage (EXIT_FAILURE); } if (args.help_given) usage (EXIT_SUCCESS); rc = shishi_init_with_paths (&sh, args.ticket_file_arg, args.system_configuration_file_arg, args.configuration_file_arg); if (rc == SHISHI_HANDLE_ERROR) error (EXIT_FAILURE, 0, _("Could not initialize libshishi.")); rc = shishi_cfg_clientkdcetype_set (sh, args.encryption_type_arg); if (rc != SHISHI_OK) error (EXIT_FAILURE, 0, _("Could not set encryption types: %s"), shishi_strerror (rc)); if (args.inputs_num > 0) { rc = shishi_parse_name (sh, args.inputs[0], (args.client_name_arg ? NULL : &args.client_name_arg), (args.realm_arg ? NULL : &args.realm_arg)); if (rc != SHISHI_OK) error (EXIT_FAILURE, 0, _("Could not parse client principal \"%s\": %s"), args.inputs[0], shishi_strerror (rc)); } if (args.inputs_num > 1) { rc = shishi_parse_name (sh, args.inputs[1], (args.server_name_arg ? NULL : &args.server_name_arg), (args.realm_arg ? NULL : &args.realm_arg)); if (rc != SHISHI_OK) error (EXIT_FAILURE, 0, _("Could not parse server principal \"%s\": %s"), args.inputs[1], shishi_strerror (rc)); } rc = shishi_cfg (sh, args.library_options_arg); if (rc != SHISHI_OK) error (EXIT_FAILURE, 0, _("Could not read library options: %s"), shishi_strerror (rc)); if (args.verbose_given > 0) shishi_cfg (sh, "verbose"); if (args.verbose_given > 1) shishi_cfg (sh, "verbose-noise"); if (args.verbose_given > 2) shishi_cfg (sh, "verbose-asn1"); if (args.verbose_given > 3) shishi_cfg (sh, "verbose-crypto"); if (args.verbose_given > 4) shishi_cfg (sh, "verbose-crypto-noise"); if (args.starttime_arg) { starttime = shishi_get_date (args.starttime_arg, NULL); if (starttime == -1) error (EXIT_FAILURE, 0, _("Invalid --starttime date `%s'"), args.starttime_arg); } else starttime = time (NULL); if (args.endtime_arg) { endtime = shishi_get_date (args.endtime_arg, &starttime); if (endtime == -1) error (EXIT_FAILURE, 0, _("Invalid --endtime date `%s'"), args.starttime_arg); } else endtime = 0; if (args.renew_till_arg) { renew_till = shishi_get_date (args.renew_till_arg, &starttime); if (renew_till == -1) error (EXIT_FAILURE, 0, _("Invalid --renew-till date `%s'"), args.renew_till_arg); } else renew_till = 0; if (args.client_name_arg) shishi_principal_default_set (sh, args.client_name_arg); if (args.realm_arg) shishi_realm_default_set (sh, args.realm_arg); if (!args.ticket_granter_arg) asprintf (&args.ticket_granter_arg, "krbtgt/%s", shishi_realm_default (sh)); if (args.list_flag) { if (!args.quiet_flag) printf (_("Tickets in `%s':\n"), shishi_tkts_default_file (sh)); rc = shishi_tkts_print_for_service (shishi_tkts_default (sh), stdout, args.server_name_arg); if (rc != SHISHI_OK) error (EXIT_FAILURE, 0, _("Could not list tickets: %s"), shishi_strerror (rc)); } else if (args.destroy_flag) { int i, removed = 0; for (i = 0; i < shishi_tkts_size (shishi_tkts_default (sh)); i++) { if (args.server_name_arg && !shishi_tkt_server_p (shishi_tkts_nth (shishi_tkts_default (sh), i), args.server_name_arg)) continue; if (args.verbose_given) { printf (_("Removing ticket:\n")); shishi_tkt_pretty_print (shishi_tkts_nth (shishi_tkts_default (sh), i), stdout); } rc = shishi_tkts_remove (shishi_tkts_default (sh), i); if (rc != SHISHI_OK) error (EXIT_FAILURE, 0, _("Could not destroy ticket %d:\n%s"), i, shishi_strerror (rc)); i--; removed++; } if (!args.quiet_flag) { if (removed == 0) printf (_("No tickets removed.\n")); else printf (ngettext ("%d ticket removed.\n", "%d tickets removed.\n", removed), removed); } } else if (args.renew_given) { error (EXIT_FAILURE, 0, "Command --renew not implemented."); } else { Shishi_tkt *tkt; Shishi_tkts_hint hint; memset (&hint, 0, sizeof (hint)); hint.client = args.client_name_arg; hint.server = args.server_name_arg ? args.server_name_arg : args.ticket_granter_arg; hint.starttime = starttime; hint.endtime = endtime; hint.renew_till = renew_till; if (args.renewable_flag) hint.tktflags |= SHISHI_TICKETFLAGS_RENEWABLE; if (args.proxiable_flag) hint.tktflags |= SHISHI_TICKETFLAGS_PROXIABLE; if (args.proxy_flag) hint.tktflags |= SHISHI_TICKETFLAGS_PROXY; if (args.forwardable_flag) hint.tktflags |= SHISHI_TICKETFLAGS_FORWARDABLE; if (args.forwarded_flag) hint.tktflags |= SHISHI_TICKETFLAGS_FORWARDED; tkt = shishi_tkts_get (shishi_tkts_default (sh), &hint); if (!tkt) error (EXIT_FAILURE, 0, _("Could not get ticket as `%s' for `%s'."), hint.client ? hint.client : shishi_principal_default (sh), hint.server); shishi_tkt_pretty_print (tkt, stdout); } shishi_tkts_expire (shishi_tkts_default (sh)); if (args.ticket_write_file_arg) shishi_tkts_default_file_set (sh, args.ticket_write_file_arg); shishi_done (sh); return EXIT_SUCCESS; }