Exemplo n.º 1
0
int
main (int argc, char *argv[])
{
  Shishi *h;
  Shishi_ap *ap;
  char *sname;
  int rc;

  printf ("sample-client (shishi " SHISHI_VERSION ")\n");

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

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

  if (argc > 1)
    sname = argv[1];
  else
    sname = shishi_server_for_local_service (h, SERVICE);

  ap = auth (h, 1, shishi_principal_default (h), sname);

  if (ap)
    rc = doit (h, ap, 1);
  else
    rc = 1;

  shishi_done (h);

  return rc;
}
Exemplo n.º 2
0
/**
 * shishi_authenticator:
 * @handle: shishi handle as allocated by shishi_init().
 *
 * This function creates a new Authenticator, populated with some
 * default values.  It uses the current time as returned by the system
 * for the ctime and cusec fields.
 *
 * Return value: Returns the authenticator or NULL on
 * failure.
 **/
Shishi_asn1
shishi_authenticator (Shishi * handle)
{
    int res;
    Shishi_asn1 node = NULL;
    struct timeval tv;
    uint32_t seqnr;

    res = gettimeofday (&tv, NULL);
    if (res != 0)
        return NULL;

    node = shishi_asn1_authenticator (handle);
    if (!node)
        return NULL;

    res = shishi_asn1_write (handle, node, "authenticator-vno", "5", 0);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_authenticator_set_crealm (handle, node,
                                           shishi_realm_default (handle));
    if (res != SHISHI_OK)
        goto error;

    res = shishi_authenticator_client_set (handle, node,
                                           shishi_principal_default (handle));
    if (res != SHISHI_OK)
        goto error;

    res = shishi_authenticator_cusec_set (handle, node, tv.tv_usec % 1000000);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_asn1_write (handle, node, "ctime",
                             shishi_generalize_time (handle, time (NULL)), 0);
    if (res != SHISHI_OK)
        goto error;

    /*
     * For sequence numbers to adequately support the detection of
     * replays they SHOULD be non-repeating, even across connection
     * boundaries. The initial sequence number SHOULD be random and
     * uniformly distributed across the full space of possible sequence
     * numbers, so that it cannot be guessed by an attacker and so that
     * it and the successive sequence numbers do not repeat other
     * sequences.
     */
    shishi_randomize (handle, 0, &seqnr, sizeof (seqnr));

    /* XXX remove once libtasn1 _asn1_convert_integer is fixed. */
    seqnr &= 0x7FFFFFFF;

    /*
     * Implementation note: as noted before, some implementations omit
     * the optional sequence number when its value would be zero.
     * Implementations MAY accept an omitted sequence number when
     * expecting a value of zero, and SHOULD NOT transmit an
     * Authenticator with a initial sequence number of zero.
     */
    if (seqnr == 0)
        seqnr++;

    res = shishi_authenticator_seqnumber_set (handle, node, seqnr);
    if (res != SHISHI_OK)
        goto error;

    return node;

error:
    shishi_asn1_done (handle, node);
    return NULL;
}
Exemplo n.º 3
0
int
main (int argc, char **argv)
{
  char *user = NULL;
  char *luser = NULL;
  char *host = NULL;
  char *port = "shell";
  char *p;
  char lport[5];

  struct passwd *pw;

  int af = AF_UNSPEC;
  struct addrinfo hint, *ai, *aip, *lai;
  struct sockaddr raddr;
  int raddrlen;
  int err, sock = -1, lsock = -1, esock = -1, i;

  int opt;

  bool verbose = false;

  char hostaddr[NI_MAXHOST];
  char portnr[NI_MAXSERV];

  char buf[3][BUFLEN], *bufp[3];
  int len[3], wlen;

  fd_set infd, outfd, infdset, outfdset, errfd;
  int maxfd;

  int flags;

#ifdef SHISHI

  Shishi *h;
  Shishi_key *enckey = NULL, *deckey = NULL;
  int rc;
  char *sname = NULL;
  int shishi = 0;
  int encryption = 0;
  int auth2 = 0;
  char *cmd, *tcmd;
  int hostlen, cmdlen;
  struct hostent *hostdata;
  char *iv = NULL;
  char *iv2 = NULL;
  char *iv3 = NULL;
  int ivlen;
  int ivlen2;
  int ivlen3;

#endif

  argv0 = argv[0];

  /* Lookup local username */

  if (!(pw = getpwuid (getuid ())))
    {
      fprintf (stderr, "%s: Could not lookup username: %s\n", argv0,
	       strerror (errno));
      return 1;
    }

  /* Process options */

#ifdef SHISHI
  while ((opt = getopt (argc, argv, "+l:p:46vsx")) != -1)
#else
  while ((opt = getopt (argc, argv, "+l:p:46v")) != -1)
#endif
    {

      switch (opt)
	{
	case 'l':
	  user = optarg;
	  break;
	case 'p':
	  port = optarg;
	  break;
	case '4':
	  af = AF_INET;
	  break;
	case '6':
	  af = AF_INET6;
	  break;
	case 'v':
	  verbose = true;
	  break;
#ifdef SHISHI
	case 's':
	  shishi = 1;
	  port = "544";
	  break;
	case 'x':
	  shishi = 1;
	  encryption = 1;
	  port = "544";
	  break;
#endif
	default:
	  fprintf (stderr, "%s: Unknown option!\n", argv0);
	  usage ();
	  return 1;
	}
    }

  if (optind == argc)
    {
      fprintf (stderr, "%s: No host specified!\n", argv0);
      usage ();
      return 1;
    }

#ifdef SHISHI

  if (!shishi)
    {
      luser = pw->pw_name;
      if (!user)
	user = luser;
    }
#endif

  host = argv[optind++];

  if ((p = strchr (host, '@')))
    {
      user = host;
      *p = '\0';
      host = p + 1;
    }

  /* Resolve hostname and try to make a connection */

  memset (&hint, '\0', sizeof (hint));
  hint.ai_family = af;
  hint.ai_socktype = SOCK_STREAM;

  err = getaddrinfo (host, port, &hint, &ai);

  if (err)
    {
      fprintf (stderr, "%s: Error looking up host: %s\n", argv0,
	       gai_strerror (err));
      return 1;
    }

  hint.ai_flags = AI_PASSIVE;

  for (aip = ai; aip; aip = aip->ai_next)
    {
      if (getnameinfo
	  (aip->ai_addr, aip->ai_addrlen, hostaddr, sizeof (hostaddr), portnr,
	   sizeof (portnr), NI_NUMERICHOST | NI_NUMERICSERV))
	{
	  fprintf (stderr, "%s: Error resolving address: %s\n", argv0,
		   strerror (errno));
	  return 1;
	}
      if (verbose)
	fprintf (stderr, "Trying %s port %s...", hostaddr, portnr);

      if ((sock =
	   socket (aip->ai_family, aip->ai_socktype, aip->ai_protocol)) == -1)
	{
	  if (verbose)
	    fprintf (stderr, " Could not open socket: %s\n",
		     strerror (errno));
	  continue;
	}

      hint.ai_family = aip->ai_family;

      /* Bind to a privileged port */

      for (i = 1023; i >= 512; i--)
	{
	  snprintf (lport, sizeof (lport), "%d", i);
	  err = getaddrinfo (NULL, lport, &hint, &lai);
	  if (err)
	    {
	      fprintf (stderr, " Error looking up localhost: %s\n",
		       gai_strerror (err));
	      return 1;
	    }

	  err = bind (sock, lai->ai_addr, lai->ai_addrlen);

	  freeaddrinfo (lai);

	  if (err)
	    continue;
	  else
	    break;
	}

      if (err)
	{
	  if (verbose)
	    fprintf (stderr, " Could not bind to privileged port: %s\n",
		     strerror (errno));
	  continue;
	}

      if (connect (sock, aip->ai_addr, aip->ai_addrlen) == -1)
	{
	  if (verbose)
	    fprintf (stderr, " Connection failed: %s\n", strerror (errno));
	  continue;
	}
      if (verbose)
	fprintf (stderr, " Connected.\n");
      break;
    }

  if (!aip)
    {
      fprintf (stderr, "%s: Could not make a connection.\n", argv0);
      return 1;
    }

  /* Create a socket for the incoming connection for stderr output */

  if ((lsock =
       socket (aip->ai_family, aip->ai_socktype, aip->ai_protocol)) == -1)
    {
      fprintf (stderr, "%s: Could not open socket: %s\n", argv0,
	       strerror (errno));
      return 1;
    }

  hint.ai_family = aip->ai_family;

  freeaddrinfo (ai);

  for (i--; i >= 512; i--)
    {
      snprintf (lport, sizeof (lport), "%d", i);
      err = getaddrinfo (NULL, lport, &hint, &lai);
      if (err)
	{
	  fprintf (stderr, "%s: Error looking up localhost: %s\n", argv0,
		   gai_strerror (err));
	  return 1;
	}

      err = bind (lsock, lai->ai_addr, lai->ai_addrlen);

      freeaddrinfo (lai);

      if (err)
	continue;
      else
	break;
    }

  if (err)
    {
      fprintf (stderr, "%s: Could not bind to privileged port: %s\n", argv0,
	       strerror (errno));
      return 1;
    }

  if (listen (lsock, 1))
    {
      fprintf (stderr, "%s: Could not listen: %s\n", argv0, strerror (errno));
      return 1;
    }

  /* Drop privileges */

  if (setuid (getuid ()))
    {
      fprintf (stderr, "%s: Unable to drop privileges: %s\n", argv0,
	       strerror (errno));
      return 1;
    }

  /* Send required information to the server */

  bufp[0] = buf[0];
  len[0] = sizeof (buf[0]);
#ifdef SHISHI

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

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

      hostdata = gethostbyname (host);
      hostlen = strlen (hostdata->h_name) + strlen (SERVICE) + 2;
      sname = malloc (hostlen);
      snprintf (sname, hostlen, "%s/%s", SERVICE, hostdata->h_name);

      rc = optind;
      cmdlen = BUFLEN;
      cmd = malloc (cmdlen);
      tcmd = cmd;

      if (encryption)
	safecpy (&tcmd, &cmdlen, "-x ", 0);

      for (; optind < argc; optind++)
	{
	  safecpy (&tcmd, &cmdlen, argv[optind], 0);
	  if (optind < argc - 1)
	    safecpy (&tcmd, &cmdlen, " ", 0);
	}

      safecpy (&tcmd, &cmdlen, "", 1);

      optind = rc;

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

      safewrite (sock, lport, strlen (lport) + 1);

      /* Wait for incoming connection from server */

      if ((esock = accept (lsock, &raddr, &raddrlen)) == -1)
	{
	  fprintf (stderr, "%s: Could not accept stderr connection: %s\n",
		   argv0, strerror (errno));
	  return 1;
	}

      close (lsock);

      if (auth (h, 0, user, sname, sock, cmd, port, &enckey, deckey) !=
	  AUTH_OK)
	return 1;

      free (cmd);

    }
  else
    {
      safecpy (&bufp[0], &len[0], lport, 1);
      safecpy (&bufp[0], &len[0], luser, 1);
    }

#else
  safecpy (&bufp[0], &len[0], lport, 1);
  safecpy (&bufp[0], &len[0], luser, 1);
#endif

  safecpy (&bufp[0], &len[0], user, 1);

#ifdef SHISHI
  if (encryption)
    safecpy (&bufp[0], &len[0], "-x ", 0);
#endif

  for (; optind < argc; optind++)
    {
      safecpy (&bufp[0], &len[0], argv[optind], 0);
      if (optind < argc - 1)
	safecpy (&bufp[0], &len[0], " ", 0);
    }

#ifdef SHISHI
  if (shishi)
    {
      safecpy (&bufp[0], &len[0], "", 1);
      safecpy (&bufp[0], &len[0], user, 1);
    }
  else
#endif

    safecpy (&bufp[0], &len[0], "", 1);

  if (!len[0])
    {
      fprintf (stderr, "%s: Arguments too long!\n", argv0);
      return 1;
    }

  if (safewrite (sock, buf[0], bufp[0] - buf[0]) == -1)
    {
      fprintf (stderr, "%s: Unable to send required information: %s\n", argv0,
	       strerror (errno));
      return 1;
    }

#ifdef SHISHI

  if (shishi)
    {
      safewrite (sock, &auth2, sizeof (int));
    }
#endif

  /* Wait for acknowledgement from server */

  errno = 0;

  if (read (sock, buf[0], 1) != 1 || *buf[0])
    {
      fprintf (stderr, "%s: Didn't receive NULL byte from server: %s\n",
	       argv0, strerror (errno));
      return 1;
    }

#ifdef SHISHI

  if (encryption)
    {
      ivlen = ivlen2 = ivlen3 = shishi_key_length (enckey);
      iv = malloc (ivlen);
      memset (iv, 1, ivlen);
      iv2 = malloc (ivlen2);
      memset (iv2, 3, ivlen2);
      iv3 = malloc (ivlen3);
      memset (iv3, 0, ivlen3);
    }

  if (!shishi)
    {

      /* Wait for incoming connection from server */

      if ((esock = accept (lsock, &raddr, &raddrlen)) == -1)
	{
	  fprintf (stderr, "%s: Could not accept stderr connection: %s\n",
		   argv0, strerror (errno));
	  return 1;
	}

      close (lsock);
    }

#else

  /* Wait for incoming connection from server */

  if ((esock = accept (lsock, &raddr, &raddrlen)) == -1)
    {
      fprintf (stderr, "%s: Could not accept stderr connection: %s\n", argv0,
	       strerror (errno));
      return 1;
    }

  close (lsock);

#endif

  /* Process input/output */

  flags = fcntl (sock, F_GETFL);
  fcntl (sock, F_SETFL, flags | O_NONBLOCK);
  flags = fcntl (esock, F_GETFL);
  fcntl (esock, F_SETFL, flags | O_NONBLOCK);

  bufp[0] = buf[0];
  bufp[1] = buf[1];
  bufp[2] = buf[2];

  FD_ZERO (&infdset);
  FD_ZERO (&outfdset);
  FD_SET (0, &infdset);
  FD_SET (sock, &infdset);
  FD_SET (esock, &infdset);

  maxfd = (sock > esock ? sock : esock) + 1;

  for (;;)
    {
      errno = 0;
      infd = infdset;
      outfd = outfdset;
      errfd = infdset;

      if (select (maxfd, &infd, &outfd, &errfd, NULL) <= 0)
	{
	  if (errno == EINTR)
	    continue;
	  else
	    break;
	}


      if (FD_ISSET (esock, &infd))
	{
#ifdef SHISHI
	  if (encryption)
	    {
	      rc = readenc (h, esock, buf[2], &len[2], iv2, &ivlen2, enckey);
	      if (rc != SHISHI_OK)
		break;
	    }
	  else
#endif
	    len[2] = read (esock, buf[2], BUFLEN);
	  if (len[2] <= 0)
	    {
	      if (errno != EINTR)
		{
		  if (FD_ISSET (sock, &infdset) || FD_ISSET (1, &outfdset))
		    FD_CLR (esock, &infdset);
		  else
		    break;
		}
	    }
	  else
	    {
	      FD_SET (2, &outfdset);
	      FD_CLR (esock, &infdset);
	    }
	}

      if (FD_ISSET (2, &outfd))
	{
	  wlen = write (2, bufp[2], len[2]);
	  if (wlen <= 0)
	    {
	      if (errno != EINTR)
		{
		  if (FD_ISSET (sock, &infdset) || FD_ISSET (1, &outfdset))
		    FD_CLR (esock, &infdset);
		  else
		    break;
		}
	    }
	  else
	    {
	      len[2] -= wlen;
	      bufp[2] += wlen;
	      if (!len[2])
		{
		  FD_CLR (2, &outfdset);
		  FD_SET (esock, &infdset);
		  bufp[2] = buf[2];
		}
	    }
	}

      if (FD_ISSET (sock, &infd))
	{
#ifdef SHISHI
	  if (encryption)
	    {
	      rc = readenc (h, sock, buf[1], &len[1], iv, &ivlen, enckey);
	      if (rc != SHISHI_OK)
		break;
	    }
	  else
#endif
	    len[1] = read (sock, buf[1], BUFLEN);
	  if (len[1] <= 0)
	    {
	      if (errno != EINTR)
		{
		  if (FD_ISSET (esock, &infdset) || FD_ISSET (2, &outfdset))
		    FD_CLR (sock, &infdset);
		  else
		    break;
		}
	    }
	  else
	    {
	      FD_SET (1, &outfdset);
	      FD_CLR (sock, &infdset);
	    }
	}

      if (FD_ISSET (1, &outfd))
	{
	  wlen = write (1, bufp[1], len[1]);
	  if (wlen <= 0)
	    {
	      if (errno != EINTR)
		{
		  if (FD_ISSET (esock, &infdset) || FD_ISSET (2, &outfdset))
		    FD_CLR (sock, &infdset);
		  else
		    break;
		}
	    }
	  else
	    {
	      len[1] -= wlen;
	      bufp[1] += wlen;
	      if (!len[1])
		{
		  FD_CLR (1, &outfdset);
		  FD_SET (sock, &infdset);
		  bufp[1] = buf[1];
		}
	    }
	}

      if (FD_ISSET (0, &infd))
	{
	  len[0] = read (0, buf[0], BUFLEN);
	  if (len[0] <= 0)
	    {
	      if (errno != EINTR)
		{
		  FD_CLR (0, &infdset);
		  shutdown (sock, SHUT_WR);
		}
	    }
	  else
	    {
	      FD_SET (sock, &outfdset);
	      FD_CLR (0, &infdset);
	    }
	}

      if (FD_ISSET (sock, &outfd))
	{
#ifdef SHISHI
	  if (encryption)
	    {
	      rc =
		writeenc (h, sock, bufp[0], len[0], &wlen, iv3, &ivlen3,
			  enckey);
	      if (rc != SHISHI_OK)
		break;
	    }
	  else
#endif
	    wlen = write (sock, bufp[0], len[0]);
	  if (wlen <= 0)
	    {
	      if (errno != EINTR)
		break;
	    }
	  else
	    {
	      len[0] -= wlen;
	      bufp[0] += wlen;
	      if (!len[0])
		{
		  FD_CLR (sock, &outfdset);
		  FD_SET (0, &infdset);
		  bufp[0] = buf[0];
		}
	    }
	}


    }

  if (errno)
    {
      fprintf (stderr, "%s: %s\n", argv0, strerror (errno));
      return 1;
    }

  close (sock);
  close (esock);

#ifdef SHISHI

  if (shishi)
    {
      shishi_done (h);
      if (encryption)
	{
	  free (iv);
	  free (iv2);
	  free (iv3);
	}
    }

#endif

  return 0;
}
Exemplo n.º 4
0
static Shishi_asn1
_shishi_kdcreq (Shishi * handle, int as)
{
    int res;
    Shishi_asn1 node;
    const char *servicebuf[3];
    uint32_t nonce;

    if (as)
        node = shishi_asn1_asreq (handle);
    else
        node = shishi_asn1_tgsreq (handle);
    if (!node)
        return NULL;

    res = shishi_asn1_write (handle, node, "pvno",
                             SHISHI_KDCREQ_DEFAULT_PVNO,
                             SHISHI_KDCREQ_DEFAULT_PVNO_LEN);
    if (res != SHISHI_OK)
        goto error;

    if (as)
        res = shishi_asn1_write (handle, node, "msg-type",
                                 SHISHI_AS_REQ_DEFAULT_MSG_TYPE,
                                 SHISHI_AS_REQ_DEFAULT_MSG_TYPE_LEN);
    else
        res = shishi_asn1_write (handle, node, "msg-type",
                                 SHISHI_TGS_REQ_DEFAULT_MSG_TYPE,
                                 SHISHI_TGS_REQ_DEFAULT_MSG_TYPE_LEN);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_asn1_write (handle, node, "req-body.kdc-options",
                             SHISHI_KDCREQ_DEFAULT_REQ_BODY_KDC_OPTIONS,
                             SHISHI_KDCREQ_DEFAULT_REQ_BODY_KDC_OPTIONS_LEN);
    if (res != SHISHI_OK)
        goto error;

    if (as)
        res = shishi_kdcreq_set_cname (handle, node, SHISHI_NT_PRINCIPAL,
                                       shishi_principal_default (handle));
    else
        res = shishi_asn1_write (handle, node, "req-body.cname", NULL, 0);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_kdcreq_set_realm (handle, node, shishi_realm_default (handle));
    if (res != SHISHI_OK)
        goto error;

    servicebuf[0] = "krbtgt";
    servicebuf[1] = shishi_realm_default (handle);
    servicebuf[2] = NULL;
    res = shishi_kdcreq_set_sname (handle, node,
                                   SHISHI_NT_PRINCIPAL, servicebuf);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_asn1_write (handle, node, "req-body.sname.name-type",
                             SHISHI_KDCREQ_DEFAULT_REQ_BODY_SNAME_NAME_TYPE,
                             SHISHI_KDCREQ_DEFAULT_REQ_BODY_SNAME_NAME_TYPE_LEN);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_asn1_write (handle, node, "req-body.till",
                             shishi_generalize_time (handle,
                                     time (NULL) +
                                     handle->ticketlife), 0);
    if (res != SHISHI_OK)
        goto error;

    shishi_randomize (handle, 0, &nonce, sizeof (nonce));
    nonce &= 0x7FFFFFFF;		/* XXX fix _libtasn1_convert_integer. */
    res = shishi_kdcreq_nonce_set (handle, node, nonce);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_kdcreq_set_etype (handle, node, handle->clientkdcetypes,
                                   handle->nclientkdcetypes);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_asn1_write (handle, node, "req-body.addresses", NULL, 0);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_asn1_write (handle, node,
                             "req-body.enc-authorization-data", NULL, 0);
    if (res != SHISHI_OK)
        goto error;

    res =
        shishi_asn1_write (handle, node, "req-body.additional-tickets", NULL, 0);
    if (res != SHISHI_OK)
        goto error;

    return node;

error:
    shishi_asn1_done (handle, node);
    return NULL;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
/* 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;

}