Beispiel #1
0
static int
doit (Shishi * h, Shishi_ap * ap, int verbose)
{
  Shishi_asn1 asn1safe;
  Shishi_safe *safe;
  char *userdata;
  size_t userdatalen;
  int res;

  printf ("Application exchange start.  Press ^D to finish.\n");

  while ((res = shishi_safe_parse (h, stdin, &asn1safe)) == SHISHI_OK)
    {
      if (res != SHISHI_OK)
	{
	  fprintf (stderr, "Could not read SAFE:\n%s\n%s\n",
		   shishi_strerror (res), shishi_error (h));
	  return 1;
	}

      res = shishi_safe (h, &safe);
      if (res != SHISHI_OK)
	{
	  fprintf (stderr, "Could not create SAFE:\n%s\n%s\n",
		   shishi_strerror (res), shishi_error (h));
	  return 1;
	}

      shishi_safe_safe_set (safe, asn1safe);

      res = shishi_safe_verify (safe, shishi_ap_key (ap));
      if (res != SHISHI_OK)
	{
	  fprintf (stderr, "Could not verify SAFE:\n%s\n%s\n",
		   shishi_strerror (res), shishi_error (h));
	  return 1;
	}

      printf ("Verified SAFE successfully...\n");

      res = shishi_safe_user_data (h, asn1safe, &userdata, &userdatalen);
      if (res != SHISHI_OK)
	{
	  fprintf (stderr, "Could not extract user data:\n%s\n%s\n",
		   shishi_strerror (res), shishi_error (h));
	  return 1;
	}
      userdata[userdatalen] = '\0';
      printf ("user data: `%s'\n", userdata);

    }

  if (ferror (stdin))
    {
      printf ("error reading stdin\n");
      return 1;
    }

  return 0;
}
Beispiel #2
0
static int
doit (Shishi * handle, Shishi_ap * ap, int verbose)
{
  char line[BUFSIZ];
  int res;

  printf ("Application exchange start.  Press ^D to finish.\n");

  while (fgets (line, sizeof (line), stdin))
    {
      Shishi_safe *safe;

      line[strlen(line)-1] = '\0';
      printf ("read: %s\n", line);

      res = shishi_safe (handle, &safe);
      if (res != SHISHI_OK)
	{
	  printf ("Could not build SAFE: %s\n", shishi_strerror (res));
	  return res;
	}

      res = shishi_safe_set_user_data (handle, shishi_safe_safe (safe),
				       line, strlen (line));
      if (res != SHISHI_OK)
	{
	  printf ("Could not set application data in SAFE: %s\n",
		  shishi_strerror (res));
	  return res;
	}

      res = shishi_safe_build (safe, shishi_ap_key (ap));
      if (res != SHISHI_OK)
	{
	  printf ("Could not build SAFE: %s\n", shishi_strerror (res));
	  return res;
	}

      res = shishi_safe_print (handle, stdout, shishi_safe_safe (safe));
      if (res != SHISHI_OK)
	{
	  printf ("Could not print SAFE: %s\n", shishi_strerror (res));
	  return res;
	}
    }

  if (ferror (stdin))
    {
      printf ("error reading stdin\n");
      return 1;
    }

  return 0;
}
Beispiel #3
0
/**
 * shishi_tgs_req_build:
 * @tgs: structure that holds information about TGS exchange
 *
 * Checksum data in authenticator and add ticket and authenticator to
 * TGS-REQ.
 *
 * Return value: Returns SHISHI_OK iff successful.
 **/
int
shishi_tgs_req_build (Shishi_tgs * tgs)
{
  uint32_t apoptions;
  int res;

  if (VERBOSE (tgs->handle))
    printf ("Building TGS-REQ...\n");

  res = shishi_kdcreq_build (tgs->handle, tgs->tgsreq);
  if (res != SHISHI_OK)
    return res;

  res = shishi_apreq_options (tgs->handle, shishi_ap_req (tgs->ap),
			      &apoptions);
  if (res != SHISHI_OK)
    {
      shishi_error_printf (tgs->handle,
			   "Could not get AP-REQ AP-Options: %s\n",
			   shishi_strerror (res));
      return res;
    }

  res = shishi_ap_set_tktoptionsasn1usage
    (tgs->ap, tgs->tgtkt, apoptions, tgs->tgsreq, "req-body",
     SHISHI_KEYUSAGE_TGSREQ_APREQ_AUTHENTICATOR_CKSUM,
     SHISHI_KEYUSAGE_TGSREQ_APREQ_AUTHENTICATOR);
  if (res == SHISHI_OK)
    res = shishi_ap_req_build (tgs->ap);
  if (res != SHISHI_OK)
    {
      shishi_error_printf (tgs->handle, "Could not make AP-REQ: %s\n",
			   shishi_strerror (res));
      return res;
    }


  if (VERBOSE (tgs->handle))
    printf ("Got AP-REQ...\n");

  if (VERBOSEASN1 (tgs->handle))
    shishi_apreq_print (tgs->handle, stdout, shishi_ap_req (tgs->ap));

  res = shishi_kdcreq_add_padata_tgs (tgs->handle, tgs->tgsreq,
				      shishi_ap_req (tgs->ap));
  if (res != SHISHI_OK)
    {
      shishi_error_printf (tgs->handle, "Could not add AP-REQ to TGS: %s\n",
			   shishi_strerror (res));
      return res;
    }

  return SHISHI_OK;
}
Beispiel #4
0
/**
 * shishi_tgs_rep_process:
 * @tgs: structure that holds information about TGS exchange
 *
 * Process new TGS-REP and set ticket.  The key to decrypt the TGS-REP
 * is taken from the EncKDCRepPart of the TGS tgticket.
 *
 * Return value: Returns SHISHI_OK iff successful.
 **/
int
shishi_tgs_rep_process (Shishi_tgs * tgs)
{
  Shishi_asn1 kdcreppart, ticket;
  int res;

  if (VERBOSE (tgs->handle))
    printf ("Processing TGS-REQ and TGS-REP...\n");

  res = shishi_tgs_process (tgs->handle, tgs->tgsreq, tgs->tgsrep,
			    shishi_ap_authenticator (tgs->ap),
			    shishi_tkt_enckdcreppart (tgs->tgtkt),
			    &kdcreppart);
  if (res != SHISHI_OK)
    {
      shishi_error_printf (tgs->handle, "Could not process TGS: %s",
			   shishi_strerror (res));
      return res;
    }

  if (VERBOSE (tgs->handle))
    printf ("Got EncKDCRepPart...\n");

  if (VERBOSEASN1 (tgs->handle))
    shishi_enckdcreppart_print (tgs->handle, stdout, kdcreppart);

  res = shishi_kdcrep_get_ticket (tgs->handle, tgs->tgsrep, &ticket);
  if (res != SHISHI_OK)
    {
      shishi_error_printf (tgs->handle,
			   "Could not extract ticket from TGS-REP: %s",
			   shishi_strerror (res));
      return res;
    }

  if (VERBOSE (tgs->handle))
    printf ("Got Ticket...\n");

  if (VERBOSEASN1 (tgs->handle))
    shishi_ticket_print (tgs->handle, stdout, ticket);

  /* XXX */
  tgs->tkt = shishi_tkt2 (tgs->handle, ticket, kdcreppart, tgs->tgsrep);

  return SHISHI_OK;
}
Beispiel #5
0
/**
 * shishi_tgs_set_realm:
 * @tgs: structure that holds information about TGS exchange
 * @realm: indicates the realm to acquire ticket for.
 *
 * Set the server in the TGS-REQ.
 *
 * Return value: Returns SHISHI_OK iff successful.
 **/
int
shishi_tgs_set_realm (Shishi_tgs * tgs, const char *realm)
{
  int res;

  res = shishi_kdcreq_set_realm (tgs->handle, tgs->tgsreq, realm);
  if (res != SHISHI_OK)
    {
      shishi_error_printf (tgs->handle,
			   "Could not set realm in KDC-REQ: %s\n",
			   shishi_strerror (res));
      return res;
    }

  return SHISHI_OK;
}
Beispiel #6
0
int
krcmd_mutual (Shishi ** h, char **ahost, unsigned short rport, char **remuser,
	      char *cmd, int *fd2p, const char *realm, Shishi_key ** key, int af)
{
  int sock = -1, err = 0;
  struct sockaddr_storage laddr, faddr;
  long authopts = SHISHI_APOPTIONS_MUTUAL_REQUIRED;

#   ifdef HAVE_GETPWUID_R
  if (!pwbuf)
    {
      pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
      if (pwbuflen <= 0)
	pwbuflen = 1024;	/* Guessing only.  */

      pwbuf = malloc (pwbuflen);
    }

  if (pwbuf)
    (void) getpwuid_r (getuid (), &pwstor, pwbuf, pwbuflen, &pwd);
#   endif /* HAVE_GETPWUID_R */

  err = kcmd (h, &sock, ahost, rport,
#   ifdef HAVE_GETPWUID_R
	      pwd ? pwd->pw_name : *remuser,	/* locuser */
#   else /* !HAVE_GETPWUID_R */
	      NULL,		/* locuser not used */
#   endif
	      remuser, cmd, fd2p,
	      SERVICE_NAME, realm,
	      key,		/* filled in */
	      &laddr,		/* filled in */
	      &faddr,		/* filled in */
	      authopts, af);

  if (err > SHISHI_OK)
    {
      fprintf (stderr, "krcmd_mutual: error %d, %s\n",
	       err, shishi_strerror (err));
      return (-1);
    }

  if (err < 0)
    return (-1);
  return (sock);
}
Beispiel #7
0
int
krcmd (Shishi ** h, char **ahost, unsigned short rport, char **remuser,
       char *cmd, int *fd2p, const char *realm, int af)
{
  int sock = -1, err = 0;
  long authopts = 0L;

#  ifdef HAVE_GETPWUID_R
  if (!pwbuf)
    {
      pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
      if (pwbuflen <= 0)
	pwbuflen = 1024;	/* Guessing only.  */

      pwbuf = malloc (pwbuflen);
    }

  if (pwbuf)
    (void) getpwuid_r (getuid (), &pwstor, pwbuf, pwbuflen, &pwd);
#  endif /* HAVE_GETPWUID_R */

  err = kcmd (h, &sock, ahost, rport,
#  ifdef HAVE_GETPWUID_R
	      pwd ? pwd->pw_name : *remuser,	/* locuser */
#  else /* !HAVE_GETPWUID_R */
	      NULL,		/* locuser not used */
#  endif
	      remuser, cmd, fd2p,
	      SERVICE_NAME, realm,
	      NULL,		/* key schedule not used */
	      NULL,		/* local addr not used */
	      NULL,		/* foreign addr not used */
	      authopts, af);

  if (err > SHISHI_OK)
    {
      fprintf (stderr, "krcmd: error %d, %s\n", err, shishi_strerror (err));
      return (-1);
    }
  if (err < 0)
    return (-1);
  return (sock);
}
Beispiel #8
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;
}
Beispiel #9
0
/**
 * shishi_kdcreq_add_padata_tgs:
 * @handle: shishi handle as allocated by shishi_init().
 * @kdcreq: KDC-REQ to add PA-DATA to.
 * @apreq: AP-REQ to add as PA-DATA.
 *
 * Add TGS pre-authentication data to KDC-REQ.  The data is an AP-REQ
 * that authenticates the request.  This functions simply DER encodes
 * the AP-REQ and calls shishi_kdcreq_add_padata() with a
 * SHISHI_PA_TGS_REQ padatatype.
 *
 * Return value: Returns SHISHI_OK iff successful.
 **/
int
shishi_kdcreq_add_padata_tgs (Shishi * handle,
                              Shishi_asn1 kdcreq, Shishi_asn1 apreq)
{
    int res;
    char *data;
    size_t datalen;

    res = shishi_asn1_to_der (handle, apreq, &data, &datalen);
    if (res != SHISHI_OK)
    {
        shishi_error_printf (handle, "Could not DER encode AP-REQ: %s\n",
                             shishi_strerror (res));
        return res;
    }

    res = shishi_kdcreq_add_padata (handle, kdcreq,
                                    SHISHI_PA_TGS_REQ, data, datalen);
    free (data);
    if (res != SHISHI_OK)
        return res;

    return res;
}
Beispiel #10
0
/**
 * shishi_apreq_add_authenticator:
 * @handle: shishi handle as allocated by shishi_init().
 * @apreq: AP-REQ to add authenticator field to.
 * @key: key to to use for encryption.
 * @keyusage: cryptographic key usage value to use in encryption.
 * @authenticator: authenticator as allocated by shishi_authenticator().
 *
 * Encrypts DER encoded authenticator using key and store it in the
 * AP-REQ.
 *
 * Return value: Returns SHISHI_OK iff successful.
 **/
int
shishi_apreq_add_authenticator (Shishi * handle,
				Shishi_asn1 apreq,
				Shishi_key * key,
				int keyusage, Shishi_asn1 authenticator)
{
  int res;
  char *buf;
  size_t buflen;
  char *der;
  size_t derlen;

  res = shishi_asn1_to_der (handle, authenticator, &der, &derlen);
  if (res != SHISHI_OK)
    {
      shishi_error_printf (handle, "Could not DER encode authenticator: %s\n",
			   shishi_strerror (res));
      return res;
    }

  res = shishi_encrypt (handle, key, keyusage, der, derlen, &buf, &buflen);

  free (der);

  if (res != SHISHI_OK)
    {
      shishi_error_printf (handle, "Cannot encrypt authenticator.\n");
      return res;
    }

  res = shishi_apreq_set_authenticator (handle, apreq, shishi_key_type (key),
					shishi_key_version (key),
					buf, buflen);

  return res;
}
Beispiel #11
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;
}
Beispiel #12
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;

}
Beispiel #13
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;
}
Beispiel #14
0
static Shishi *
init_handle (int outputtype)
{
  Shishi *handle;
  int rc;

  handle = xcalloc (1, sizeof (*handle));

  shishi_error_set_outputtype (handle, outputtype);

  if (!shishi_check_version (SHISHI_VERSION))
    {
      shishi_warn (handle, "Library and header version missmatch (%s vs %s).",
		   shishi_check_version (NULL), SHISHI_VERSION);
      free (handle);
      return NULL;
    }

  rc = gl_sockets_startup (SOCKETS_2_1);
  if (rc)
    {
      shishi_warn (handle, "Failed to initialized Windows sockets (%d)", rc);
      free (handle);
      return NULL;
    }

  rc = _shishi_crypto_init (handle);
  if (rc != SHISHI_OK)
    {
      shishi_warn (handle, "Cannot initialize crypto library");
      free (handle);
      return NULL;
    }

#ifdef USE_STARTTLS
  rc = _shishi_tls_init (handle);
  if (rc != SHISHI_OK)
    {
      shishi_warn (handle, "Cannot initialize TLS library");
      free (handle);
      return NULL;
    }
#endif

  rc = _shishi_asn1_init (handle);
  if (rc != SHISHI_OK)
    {
      shishi_warn (handle, "%s", shishi_strerror (SHISHI_ASN1_ERROR));
      free (handle);
      return NULL;
    }

  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  handle->kdctimeout = 5;
  handle->kdcretries = 3;

  handle->ticketlife = TICKETLIFE;
  handle->renewlife = RENEWLIFE;

  handle->nclientkdcetypes = 1;
  handle->clientkdcetypes = xmalloc (sizeof (*handle->clientkdcetypes) *
				     handle->nclientkdcetypes);
  handle->clientkdcetypes[0] = SHISHI_AES256_CTS_HMAC_SHA1_96;

  handle->nauthorizationtypes = 1;
  handle->authorizationtypes = xmalloc (sizeof (*handle->authorizationtypes) *
					handle->nauthorizationtypes);
  handle->authorizationtypes[0] = SHISHI_AUTHORIZATION_BASIC;

  return handle;
}
Beispiel #15
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;
}
Beispiel #16
0
static Shishi_ap *
auth (Shishi * h, int verbose, const char *cname, const char *sname)
{
  Shishi_key *key;
  Shishi_ap *ap;
  Shishi_asn1 apreq;
  char *buf;
  size_t buflen;
  int rc;

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

  /* Get key for the server. */

  key = shishi_hostkeys_for_server (h, sname);
  if (!key)
    {
      printf ("could not find key: %s\n", shishi_error (h));
      return NULL;
    }

  if (verbose)
    shishi_key_print (h, stderr, key);

  /* Read Authentication request from client */

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

  rc = shishi_apreq_parse (h, stdin, &apreq);
  if (rc != SHISHI_OK)
    {
      printf ("could not read AP-REQ: %s\n", shishi_strerror (rc));
      return NULL;
    }

  /* Create Authentication context */

  rc = shishi_ap (h, &ap);
  if (rc != SHISHI_OK)
    {
      printf ("Could not create AP: %s\n", shishi_strerror (rc));
      return NULL;
    }

  /* Store request in context */

  shishi_ap_req_set (ap, apreq);

  /* Process authentication request */

  rc = shishi_ap_req_process (ap, key);
  if (rc != SHISHI_OK)
    {
      printf ("Could not process AP-REQ: %s\n", shishi_strerror (rc));
      return NULL;
    }

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

  rc = shishi_authenticator_client (h, shishi_ap_authenticator (ap),
				    &buf, &buflen);
  printf ("Client name (from authenticator): %.*s\n", (int) buflen, buf);
  free (buf);

  rc = shishi_encticketpart_clientrealm
    (h, shishi_tkt_encticketpart (shishi_ap_tkt (ap)), &buf, &buflen);
  printf ("Client name (from encticketpart): %.*s\n", (int) buflen, buf);
  free (buf);

  rc = shishi_ticket_server (h, shishi_tkt_ticket (shishi_ap_tkt (ap)),
			     &buf, &buflen);
  printf ("Server name (from ticket): %.*s\n", (int) buflen, buf);
  free (buf);

  /* User is authenticated. */

  printf ("User authenticated.\n");

  /* Authenticate ourself to client, if request */

  if (shishi_apreq_mutual_required_p (h, apreq))
    {
      Shishi_asn1 aprep;

      printf ("Mutual authentication required.\n");

      rc = shishi_ap_rep_asn1 (ap, &aprep);
      if (rc != SHISHI_OK)
	{
	  printf ("Error creating AP-REP: %s\n", shishi_strerror (rc));
	  return NULL;
	}

      if (verbose)
	shishi_encapreppart_print (h, stderr, shishi_ap_encapreppart (ap));

      shishi_aprep_print (h, stdout, aprep);

      /* We are authenticated to client */
    }

  return ap;
}
Beispiel #17
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
}
Beispiel #18
0
/* Allows a remotely initiated security context between the
   application and a remote peer to be established, using krb5.
   Assumes context_handle is valid. */
OM_uint32
gss_krb5_accept_sec_context (OM_uint32 * minor_status,
                             gss_ctx_id_t * context_handle,
                             const gss_cred_id_t acceptor_cred_handle,
                             const gss_buffer_t input_token_buffer,
                             const gss_channel_bindings_t input_chan_bindings,
                             gss_name_t * src_name,
                             gss_OID * mech_type,
                             gss_buffer_t output_token,
                             OM_uint32 * ret_flags,
                             OM_uint32 * time_rec,
                             gss_cred_id_t * delegated_cred_handle)
{
    gss_buffer_desc data;
    char *in;
    size_t inlen;
    gss_ctx_id_t cx;
    _gss_krb5_ctx_t cxk5;
    _gss_krb5_cred_t crk5;
    int rc;

    if (minor_status)
        *minor_status = 0;

    if (ret_flags)
        *ret_flags = 0;

    if (!acceptor_cred_handle)
        /* XXX support GSS_C_NO_CREDENTIAL: acquire_cred() default server */
        return GSS_S_NO_CRED;

    if (*context_handle)
        return GSS_S_FAILURE;

    crk5 = acceptor_cred_handle->krb5;

    cx = calloc (sizeof (*cx), 1);
    if (!cx)
    {
        if (minor_status)
            *minor_status = ENOMEM;
        return GSS_S_FAILURE;
    }

    cxk5 = calloc (sizeof (*cxk5), 1);
    if (!cxk5)
    {
        free (cx);
        if (minor_status)
            *minor_status = ENOMEM;
        return GSS_S_FAILURE;
    }

    cx->mech = GSS_KRB5;
    cx->krb5 = cxk5;
    /* XXX cx->peer?? */
    *context_handle = cx;

    cxk5->sh = crk5->sh;
    cxk5->key = crk5->key;
    cxk5->acceptor = 1;

    rc = shishi_ap (cxk5->sh, &cxk5->ap);
    if (rc != SHISHI_OK)
        return GSS_S_FAILURE;

    rc = gss_decapsulate_token (input_token_buffer, GSS_KRB5, &in, &inlen);
    if (!rc)
        return GSS_S_BAD_MIC;

    if (inlen < TOK_LEN)
        return GSS_S_BAD_MIC;

    if (memcmp (in, TOK_AP_REQ, TOK_LEN) != 0)
        return GSS_S_BAD_MIC;

    rc = shishi_ap_req_der_set (cxk5->ap, in + TOK_LEN, inlen - TOK_LEN);
    if (rc != SHISHI_OK)
        return GSS_S_FAILURE;

    rc = shishi_ap_req_process (cxk5->ap, crk5->key);
    if (rc != SHISHI_OK)
    {
        if (minor_status)
            *minor_status = GSS_KRB5_S_G_VALIDATE_FAILED;
        return GSS_S_FAILURE;
    }

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

    rc = _gss_krb5_checksum_parse (minor_status,
                                   context_handle,
                                   input_chan_bindings);
    if (rc != GSS_S_COMPLETE)
        return GSS_S_FAILURE;

    cxk5->tkt = shishi_ap_tkt (cxk5->ap);
    cxk5->key = shishi_ap_key (cxk5->ap);

    if (shishi_apreq_mutual_required_p (crk5->sh, shishi_ap_req (cxk5->ap)))
    {
        Shishi_asn1 aprep;

        rc = shishi_ap_rep_asn1 (cxk5->ap, &aprep);
        if (rc != SHISHI_OK)
        {
            printf ("Error creating AP-REP: %s\n", shishi_strerror (rc));
            return GSS_S_FAILURE;
        }

        rc = shishi_encapreppart_seqnumber_get (cxk5->sh,
                                                shishi_ap_encapreppart (cxk5->
                                                        ap),
                                                &cxk5->acceptseqnr);
        if (rc != SHISHI_OK)
        {
            /* A strict 1964 implementation would return
               GSS_S_DEFECTIVE_TOKEN here.  gssapi-cfx permit absent
               sequence number, though. */
            cxk5->acceptseqnr = 0;
        }

        {
            char *der;
            size_t len;

            rc = shishi_asn1_to_der (crk5->sh, aprep, &der, &len);
            if (rc != SHISHI_OK)
            {
                printf ("Error der encoding aprep: %s\n", shishi_strerror (rc));
                return GSS_S_FAILURE;
            }
            data.value = der;
            data.length = len;
        }

        rc = gss_encapsulate_token_prefix (&data, TOK_AP_REP, TOK_LEN,
                                           GSS_KRB5, output_token);
        if (!rc)
            return GSS_S_FAILURE;

        if (ret_flags)
            *ret_flags = GSS_C_MUTUAL_FLAG;
    }
    else
    {
        output_token->value = NULL;
        output_token->length = 0;
    }

    if (src_name)
    {
        gss_name_t p;

        p = malloc (sizeof (*p));
        if (!p)
        {
            if (minor_status)
                *minor_status = ENOMEM;
            return GSS_S_FAILURE;
        }

        rc = shishi_encticketpart_client (cxk5->sh,
                                          shishi_tkt_encticketpart (cxk5->tkt),
                                          &p->value, &p->length);
        if (rc != SHISHI_OK)
            return GSS_S_FAILURE;

        p->type = GSS_KRB5_NT_PRINCIPAL_NAME;

        *src_name = p;
    }

    /* PROT_READY is not mentioned in 1964/gssapi-cfx but we support
       it anyway. */
    if (ret_flags)
        *ret_flags |= GSS_C_PROT_READY_FLAG;

    if (minor_status)
        *minor_status = 0;
    return GSS_S_COMPLETE;
}