Exemplo n.º 1
0
/* shishi authentication */
int
auth (Shishi * h, int verbose, const char *cname, const char *sname, int sock,
      char *cmd, char *port, Shishi_key ** enckey, Shishi_key * deckey)
{
  Shishi_ap *ap;
  Shishi_tkt *tkt;
  Shishi_tkts_hint hint;

  int rc;
  char *out;
  int outlen;
  int krb5len, msglen;
  char auth;
  /* KERBEROS 5 SENDAUTH MESSAGE */
  char krb5sendauth[] = "KRB5_SENDAUTH_V1.0";
  /* PROTOCOL VERSION */
  char krb5sendclient[] = "KCMDV0.2";
  /* to store error msg sent by server */
  char errormsg[101];
  char cksumdata[101];

  /* size of KRB5 auth message */
  krb5len = strlen (krb5sendauth) + 1;
  msglen = htonl (krb5len);
  safewrite (sock, &msglen, sizeof (int));
  /* KRB5 authentication message */
  safewrite (sock, krb5sendauth, krb5len);
  /* size of client message */
  krb5len = strlen (krb5sendclient) + 1;
  msglen = htonl (krb5len);
  safewrite (sock, &msglen, sizeof (int));
  /* KRB5 client message */
  safewrite (sock, krb5sendclient, krb5len);

  /* get answer from server 0 = ok, 1 = error with message */
  read (sock, &auth, 1);
  if (auth)
    {
      read (sock, errormsg, 100);
      errormsg[100] = '\0';

      printf ("Error during server authentication : %s\n", errormsg);
      return 1;
    }

  if (verbose)
    {
      printf ("Client: %s\n", cname);
      printf ("Server: %s\n", sname);
    }

  /* Get a ticket for the server. */

  memset (&hint, 0, sizeof (hint));

  hint.client = (char *) cname;
  hint.server = (char *) sname;

  tkt = shishi_tkts_get (shishi_tkts_default (h), &hint);
  if (!tkt)
    {
      printf ("cannot find ticket for \"%s\"\n", sname);
      return 1;
    }

  if (verbose)
    shishi_tkt_pretty_print (tkt, stderr);

  /* Create Authentication context */

  rc = shishi_ap_tktoptions (h, &ap, tkt, SHISHI_APOPTIONS_MUTUAL_REQUIRED);
  if (rc != SHISHI_OK)
    {
      printf ("cannot create authentication context\n");
      return 1;
    }


  /* checksum = port: terminal name */

  snprintf (cksumdata, 100, "%s:%s%s", port, cmd, cname);

  /* add checksum to authenticator */

  shishi_ap_authenticator_cksumdata_set (ap, cksumdata, strlen (cksumdata));
  /* To be compatible with MIT rlogind */
  shishi_ap_authenticator_cksumtype_set (ap, SHISHI_RSA_MD5);

  /* create der encoded AP-REQ */

  rc = shishi_ap_req_der (ap, &out, &outlen);
  if (rc != SHISHI_OK)
    {
      printf ("cannot build authentication request: %s\n",
	      shishi_strerror (rc));

      return 1;
    }

  if (verbose)
    shishi_authenticator_print (h, stderr, shishi_ap_authenticator (ap));

  /* extract subkey if present from ap exchange for secure connection */

  shishi_authenticator_get_subkey (h, shishi_ap_authenticator (ap), enckey);

  /* send size of AP-REQ to the server */

  msglen = htonl (outlen);
  safewrite (sock, (char *) &msglen, sizeof (int));

  /* send AP-REQ to the server */

  safewrite (sock, out, outlen);

  /* read a respond from server - what ? */

  read (sock, &auth, sizeof (int));

  /* For mutual authentication, wait for server reply. */

  if (shishi_apreq_mutual_required_p (h, shishi_ap_req (ap)))
    {
      if (verbose)
	printf ("Waiting for server to authenticate itself...\n");

      /* read size of the AP-REP */

      read (sock, (char *) &outlen, sizeof (int));

      /* read AP-REP */
      outlen = ntohl (outlen);
      outlen = read (sock, out, outlen);

      rc = shishi_ap_rep_verify_der (ap, out, outlen);
      if (rc == SHISHI_OK)
	{
	  if (verbose)
	    printf ("AP-REP verification OK...\n");
	}
      else
	{
	  if (rc == SHISHI_APREP_VERIFY_FAILED)
	    printf ("AP-REP verification failed...\n");
	  else
	    printf ("AP-REP verification error: %s\n", shishi_strerror (rc));
	  return 1;
	}

      /* The server is authenticated. */
      if (verbose)
	printf ("Server authenticated.\n");
    }

  /* We are now authenticated. */
  if (verbose)
    printf ("User authenticated.\n");

  return AUTH_OK;

}
Exemplo n.º 2
0
/* Request part of gss_krb5_init_sec_context.  Assumes that
   context_handle is valid, and has krb5 specific structure, and that
   output_token is valid and cleared. */
static OM_uint32
init_request (OM_uint32 * minor_status,
              const gss_cred_id_t initiator_cred_handle,
              gss_ctx_id_t * context_handle,
              const gss_name_t target_name,
              const gss_OID mech_type,
              OM_uint32 req_flags,
              OM_uint32 time_req,
              const gss_channel_bindings_t input_chan_bindings,
              const gss_buffer_t input_token,
              gss_OID * actual_mech_type,
              gss_buffer_t output_token,
              OM_uint32 * ret_flags, OM_uint32 * time_rec)
{
    gss_ctx_id_t ctx = *context_handle;
    _gss_krb5_ctx_t k5 = ctx->krb5;
    char *cksum, *der;
    size_t cksumlen;
    int rc;
    OM_uint32 maj_stat;
    gss_buffer_desc tmp;
    Shishi_tkts_hint hint;

    /* Get service ticket. */
    maj_stat = gss_krb5_canonicalize_name (minor_status, target_name,
                                           GSS_C_NO_OID, &k5->peerptr);
    if (GSS_ERROR (maj_stat))
        return maj_stat;

    memset (&hint, 0, sizeof (hint));
    hint.server = k5->peerptr->value;
    hint.endtime = time_req;

    k5->tkt = shishi_tkts_get (shishi_tkts_default (k5->sh), &hint);
    if (!k5->tkt)
    {
        if (minor_status)
            *minor_status = GSS_KRB5_S_KG_CCACHE_NOMATCH;
        return GSS_S_NO_CRED;
    }

    /* Create Authenticator checksum field. */
    maj_stat = _gss_krb5_checksum_pack (minor_status, initiator_cred_handle,
                                        context_handle,
                                        input_chan_bindings, req_flags,
                                        &cksum, &cksumlen);
    if (GSS_ERROR (maj_stat))
        return maj_stat;

    /* Create AP-REQ in output_token. */
    rc = shishi_ap_tktoptionsraw (k5->sh, &k5->ap, k5->tkt,
                                  SHISHI_APOPTIONS_MUTUAL_REQUIRED,
                                  0x8003, cksum, cksumlen);
    free (cksum);
    if (rc != SHISHI_OK)
        return GSS_S_FAILURE;

    rc = shishi_authenticator_seqnumber_get (k5->sh,
            shishi_ap_authenticator (k5->ap),
            &k5->initseqnr);
    if (rc != SHISHI_OK)
        return GSS_S_FAILURE;

    rc = shishi_ap_req_der (k5->ap, &der, &tmp.length);
    if (rc != SHISHI_OK)
        return GSS_S_FAILURE;

    tmp.value = der;

    rc = gss_encapsulate_token_prefix (&tmp, TOK_AP_REQ, TOK_LEN,
                                       GSS_KRB5, output_token);
    free (der);
    if (!rc)
        return GSS_S_FAILURE;

    if (req_flags & GSS_C_MUTUAL_FLAG)
        return GSS_S_CONTINUE_NEEDED;

    return GSS_S_COMPLETE;
}
Exemplo n.º 3
0
static Shishi_ap *
auth (Shishi * h, int verbose, const char *cname, const char *sname)
{
  Shishi_ap *ap;
  Shishi_tkt *tkt;
  Shishi_tkts_hint hint;
  int rc;

  printf ("Client: %s\n", cname);
  printf ("Server: %s\n", sname);

  /* Get a ticket for the server. */

  memset (&hint, 0, sizeof (hint));
  hint.client = (char *) cname;
  hint.server = (char *) sname;
  tkt = shishi_tkts_get (shishi_tkts_default (h), &hint);
  if (!tkt)
    {
      printf ("cannot find ticket for \"%s\"\n", sname);
      return NULL;
    }

  if (verbose)
    shishi_tkt_pretty_print (tkt, stderr);

  /* Create Authentication context */

  rc = shishi_ap_tktoptions (h, &ap, tkt, SHISHI_APOPTIONS_MUTUAL_REQUIRED);
  if (rc != SHISHI_OK)
    {
      printf ("cannot create authentication context\n");
      return NULL;
    }

  /* Build Authentication request */

  rc = shishi_ap_req_build (ap);
  if (rc != SHISHI_OK)
    {
      printf ("cannot build authentication request: %s\n",
	      shishi_strerror (rc));
      return NULL;
    }

  if (verbose)
    shishi_authenticator_print (h, stderr, shishi_ap_authenticator (ap));

  /* Authentication ourself to server */

  shishi_apreq_print (h, stdout, shishi_ap_req (ap));
  /* Note: to get the binary blob to send, use:
   *
   * char *out; int outlen;
   * ...
   * rc = shishi_ap_req_der (ap, &out, &outlen);
   * ...
   * write(fd, out, outlen);
   */

  /* For mutual authentication, wait for server reply. */

  if (shishi_apreq_mutual_required_p (h, shishi_ap_req (ap)))
    {
      Shishi_asn1 aprep;

      printf ("Waiting for server to authenticate itself...\n");

      rc = shishi_aprep_parse (h, stdin, &aprep);
      if (rc != SHISHI_OK)
	{
	  printf ("Cannot parse AP-REP from server: %s\n",
		  shishi_strerror (rc));
	  return NULL;
	}

      rc = shishi_ap_rep_verify_asn1 (ap, aprep);
      if (rc == SHISHI_OK)
	printf ("AP-REP verification OK...\n");
      else
	{
	  if (rc == SHISHI_APREP_VERIFY_FAILED)
	    printf ("AP-REP verification failed...\n");
	  else
	    printf ("AP-REP verification error: %s\n", shishi_strerror (rc));
	  return NULL;
	}

      /* The server is authenticated. */
      printf ("Server authenticated.\n");
    }

  /* We are now authenticated. */
  printf ("User authenticated.\n");

  return ap;
}
Exemplo n.º 4
0
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;
}