예제 #1
0
파일: shishi.c 프로젝트: dmr0605/Kerberos
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;
}
예제 #2
0
/* 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
}
예제 #3
0
파일: shishi.c 프로젝트: millken/zhuxianB30
/* shishi authentication */
int
shishi_auth (Shishi ** handle, int verbose, char **cname,
	     const char *sname, int sock,
	     char *cmd, int port, Shishi_key ** enckey, char *realm)
{
  Shishi_ap *ap;
  Shishi_tkt *tkt;
  Shishi_tkts_hint hint;
  Shishi *h;

  int rc;
  char *out;
  int outlen;
  int krb5len, msglen;
  char *tmpserver;
  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];

  if (!shishi_check_version (SHISHI_VERSION))
    {
      fprintf (stderr, "shishi_check_version() failed:\n"
	       "Header file incompatible with shared library.\n");
      return 1;
    }

  if (realm)
    shishi_realm_default_set (*handle, realm);

  rc = shishi_init (handle);
  if (rc != SHISHI_OK)
    {
      fprintf (stderr,
	       "error initializing shishi: %s\n", shishi_strerror (rc));
      return 1;
    }

  h = *handle;

  if (!*cname)
    *cname = (char *) shishi_principal_default (h);

  /* size of KRB5 auth message */
  krb5len = strlen (krb5sendauth) + 1;
  msglen = htonl (krb5len);
  write (sock, &msglen, sizeof (int));
  /* KRB5 authentication message */
  write (sock, krb5sendauth, krb5len);
  /* size of client message */
  krb5len = strlen (krb5sendclient) + 1;
  msglen = htonl (krb5len);
  write (sock, &msglen, sizeof (int));
  /* KRB5 client message */
  write (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';

      fprintf (stderr, "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));

  tmpserver = malloc (strlen (SERVICE) + strlen (sname) + 2);
  if (!tmpserver)
    {
      perror ("shishi_auth()");
      return 1;
    }
  strcpy (tmpserver, SERVICE);
  strcat (tmpserver, "/");
  strcat (tmpserver, sname);

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

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

  free (tmpserver);

  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)
    {
      fprintf (stderr, "cannot create authentication context\n");
      return 1;
    }


  /* checksum = port: terminal name */

  snprintf (cksumdata, 100, "%u:%s%s", ntohs (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)
    {
      fprintf (stderr, "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 */

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

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

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

  /* send AP-REQ to the server */

  write (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)
	    fprintf (stderr, "AP-REP verification failed...\n");
	  else
	    fprintf (stderr, "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 0;

}