/* serverconn.c --
 *
 * Connect to the server, then do the authentication using the appropriate
 * authentication method {Kerberos V4 uses krb_sendauth()}, and then return
 * the socket if that is successful (we probably want to do mutual
 * authentication, just to make sure that the appropriate server is really
 * getting the message, even though it really doesn't matter, since it is
 * a public key.  Return the socket on success or -1 on error.
 *
 * Created by:	Derek Atkins <warlord@MIT.EDU>
 *
 * Copyright 1994 Derek A. Atkins and the Massachusetts Institute of
 * Technology
 *
 * For copying and distribution information, please see the file
 * <warlord-copyright.h>.
 *
 * $Source: /home/warlord/athena/C/pgpsign/src/RCS/serverconn.c,v $
 * $Author: warlord $
 */

#include "warlord-copyright.h"
#include "pgpsign.h"

#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif

int
serverconnect(struct hostent *hp, int port, char *authtype)
{
  struct sockaddr_in sin, faddr;
  int sock;
  KTEXT_ST ktext;
  CREDENTIALS cred;
  MSG_DAT data;
  Key_schedule schedule;
  int retval;
  char hostname[MAXHOSTNAMELEN];

  /* Check args */
  assert (hp != NULL);
  assert (port >= 0);
  assert (authtype != NULL);

  sin.sin_family = hp->h_addrtype;
  bcopy (hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
  sin.sin_port = port;
  strncpy (hostname, hp->h_name, MAXHOSTNAMELEN);

  if ((sock = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
    perror("socket");
    return -1;
  }
 
  if (connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) {
    perror("connect");
    return -1;
  }

  retval = sizeof(struct sockaddr_in);
  if (getpeername(sock, (struct sockaddr *)&faddr, &retval) != 0) {
    perror("getpeername");
    close(sock);
    return -1;
  }

  /* Check the authtype.  Currently, only KRB4 is supported! */
  if (strcmp(authtype, AUTHTYPEKRB4)) {
    fprintf(stderr, "Unknown Authentication Type: %s\n", authtype);
    return -1;
  }

  if (krb_net_write(sock, authtype, AUTHTYPELEN) != AUTHTYPELEN) {
    perror("krb_net_write");
    close(sock);
    return -1;
  }

  /* Based upon authtype, perform appropriate authentication */
  /* XXX: Only KRB4 is supported, and multiple switched hooks are not */
  retval = krb_sendauth(0, sock, &ktext, PGPSERVICE, 
			hostname, krb_realmofhost(hostname), 
			0, &data, &cred, schedule, &sin, &faddr, "PSN0.0");

  if (retval != KSUCCESS) {
    fprintf(stderr, "%s: Kerberos Error while authenticating (%d)\n", whoami,
	    retval);
    close(sock);
    return -1;
  }

  /* Destroy all pertinent authentication data */
  bzero(&ktext, sizeof(KTEXT_ST));
  bzero(&cred, sizeof(CREDENTIALS));
  bzero(&data, sizeof(MSG_DAT));
  bzero(&schedule, sizeof(Key_schedule));

  return(sock);
}

