Exemple #1
0
static int
verify_krb4(struct passwd *pwd,
	    char *password,
	    int32_t *exp,
	    int quiet)
{
    int ret = 1;
    char lrealm[REALM_SZ];
    
    if (krb_get_lrealm (lrealm, 1) != KFAILURE) {
	set_krbtkfile(pwd->pw_uid);
	ret = krb_verify_user (pwd->pw_name, "", lrealm, password,
			       KRB_VERIFY_SECURE, NULL);
	if (ret == KSUCCESS) {
	    if (!pag_set && k_hasafs()) {
		k_setpag ();
		pag_set = 1;
            }
            if (pag_set)
		krb_afslog_uid_home (0, 0, pwd->pw_uid, pwd->pw_dir);
	} else if (!quiet)
	    printf ("%s\n", krb_get_err_text (ret));
    }
    return ret;
}
Exemple #2
0
static int
krb4_decode(void *app_data, void *buf, int len, int level,
            struct connectdata *conn)
{
    MSG_DAT m;
    int e;
    struct krb4_data *d = app_data;

    if(level == prot_safe)
        e = krb_rd_safe(buf, len, &d->key,
                        (struct sockaddr_in *)REMOTE_ADDR,
                        (struct sockaddr_in *)LOCAL_ADDR, &m);
    else
        e = krb_rd_priv(buf, len, d->schedule, &d->key,
                        (struct sockaddr_in *)REMOTE_ADDR,
                        (struct sockaddr_in *)LOCAL_ADDR, &m);
    if(e)
    {
        struct SessionHandle *data = conn->data;
        infof(data, "krb4_decode: %s\n", krb_get_err_text(e));
        return -1;
    }
    memmove(buf, m.app_data, m.app_length);
    return m.app_length;
}
Exemple #3
0
static int
krb4_adat(void *app_data, void *buf, size_t len)
{
    KTEXT_ST tkt;
    AUTH_DAT auth_dat;
    char *p;
    int kerror;
    uint32_t cs;
    char msg[35]; /* size of encrypted block */
    int tmp_len;
    struct krb4_data *d = app_data;
    char inst[INST_SZ];
    struct sockaddr_in *his_addr_sin = (struct sockaddr_in *)his_addr;

    memcpy(tkt.dat, buf, len);
    tkt.length = len;

    k_getsockinst(0, inst, sizeof(inst));
    kerror = krb_rd_req(&tkt, "ftp", inst, 
			his_addr_sin->sin_addr.s_addr, &auth_dat, "");
    if(kerror == RD_AP_UNDEC){
	k_getsockinst(0, inst, sizeof(inst));
	kerror = krb_rd_req(&tkt, "rcmd", inst, 
			    his_addr_sin->sin_addr.s_addr, &auth_dat, "");
    }

    if(kerror){
	reply(535, "Error reading request: %s.", krb_get_err_text(kerror));
	return -1;
    }
    
    memcpy(d->key, auth_dat.session, sizeof(d->key));
    des_set_key(&d->key, d->schedule);

    strlcpy(d->name, auth_dat.pname, sizeof(d->name));
    strlcpy(d->instance, auth_dat.pinst, sizeof(d->instance));
    strlcpy(d->realm, auth_dat.prealm, sizeof(d->instance));

    cs = auth_dat.checksum + 1;
    {
	unsigned char tmp[4];
	KRB_PUT_INT(cs, tmp, 4, sizeof(tmp));
	tmp_len = krb_mk_safe(tmp, msg, 4, &d->key,
			      (struct sockaddr_in *)LOCAL_ADDR,
			      (struct sockaddr_in *)REMOTE_ADDR);
    }
    if(tmp_len < 0){
	reply(535, "Error creating reply: %s.", strerror(errno));
	return -1;
    }
    len = tmp_len;
    if(base64_encode(msg, len, &p) < 0) {
	reply(535, "Out of memory base64-encoding.");
	return -1;
    }
    reply(235, "ADAT=%s", p);
    sec_complete = 1;
    free(p);
    return 0;
}
Exemple #4
0
static int
do_afslog(const char *cell)
{
    int k5ret, k4ret;

    k5ret = k4ret = 0;

#ifdef KRB5
    if(context != NULL && id != NULL && use_krb5) {
	k5ret = krb5_afslog(context, id, cell, realm);
	if(k5ret == 0)
	    return 0;
    }
#endif
#if KRB4
    if (use_krb4) {
	k4ret = krb_afslog(cell, realm);
	if(k4ret == 0)
	    return 0;
    }
#endif
    if (cell == NULL)
	cell = "<default cell>";
#ifdef KRB5
    if (k5ret)
	warnx("krb5_afslog(%s): %s", cell, krb5_get_err_text(context, k5ret));
#endif
#ifdef KRB4
    if (k4ret)
	warnx("krb_afslog(%s): %s", cell, krb_get_err_text(k4ret));
#endif
    if (k5ret || k4ret)
	return 1;
    return 0;
}
Exemple #5
0
static int
kvno4(krb5_context ctx, const char *host, krb5_principal sprinc)
{
	krb5_error_code	kerr;
	KTEXT_ST	req;
	CREDENTIALS	creds;
	int		err = 0;
	char		name[ANAME_SZ];
	char		instance[INST_SZ];
	char		realm[REALM_SZ];

	VERBOSE(1, (stderr, "initiating kvno4/udp ping to %s\n", host));

	kerr = krb5_524_conv_principal(ctx, sprinc, name, instance, realm);
	if (kerr) {
		fail_msg("kvno4", SOCK_DGRAM, host, error_message(kerr));
		goto bail;
	}

	err = krb_mk_req(&req, name, instance, realm, 0);
	if (err)
		goto bail;

        err = krb_get_cred(name, instance, realm, &creds);
        if (err)
		goto bail;

	VERBOSE(2, (stderr, "%s.%s@%s kvno = %d\n", name, instance, realm,
	    creds.kvno));

bail:
	if (err)
		fail_msg("kvno4", SOCK_DGRAM, host, krb_get_err_text(err));
	return err;
}
Exemple #6
0
static int
k4ping(krb5_context ctx, const char *host, krb5_principal princ,
    const char *passwd, krb5_principal sprinc)
{
	krb5_error_code	kerr;
	int		ret;
	char		name[ANAME_SZ];
	char		instance[INST_SZ];
	char		realm[REALM_SZ];

	VERBOSE(1, (stderr, "initiating kerberos4/udp ping to %s\n", host));
	parse_kdc(host);
	kerr = krb5_524_conv_principal(ctx, princ, name, instance, realm);
	if (kerr) {
		fail_msg("kerberos4", SOCK_DGRAM, host, error_message(kerr));
		ret = 1;
		goto bail;
	}

	ret = krb_get_pw_in_tkt(name, instance, realm, "krbtgt",
	    realm, 3600 /* seconds */, (char *)passwd);
	if (ret) {
		fail_msg("kerberos4", SOCK_DGRAM, host, krb_get_err_text(ret));
		goto bail;
	}
	ret = kvno4(ctx, host, sprinc);
	/* XXXrcd */
	k_logout_k4(ctx, NULL, K_OPT_NONE);

bail:
	return ret;
}
Exemple #7
0
/*
 * Function: Abort the authentication process
 *
 * Parameters:
 *	ks - kstream to send abort message to.
 */
static void
auth_abort(kstream ks, char *errmsg, long r)
{
  char buf[9];
  
  wsprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
	   TELQUAL_IS, AUTHTYPE_NULL,
	   AUTHTYPE_NULL, IAC, SE);
  TelnetSend(ks, (LPSTR)buf, 8, 0);
  
  if (errmsg != NULL) {
    strTmp[sizeof(strTmp) - 1] = '\0';
    strncpy(strTmp, errmsg, sizeof(strTmp) - 1);
    
    if (r != KSUCCESS) {
      strncat(strTmp, "\n", sizeof(strTmp) - 1 - strlen(strTmp));
#ifdef KRB4
      lstrcat(strTmp, krb_get_err_text((int)r));
#endif
#ifdef KRB5
      lstrcat(strTmp, error_message(r));
#endif
    }
    
    MessageBox(HWND_DESKTOP, strTmp, "Kerberos authentication failed!",
	       MB_OK | MB_ICONEXCLAMATION);
  }
}
Exemple #8
0
int					/* R: -1 on failure, else 0 */
auth_krb4_init (
  /* PARAMETERS */
  void					/* no parameters */
  /* END PARAMETERS */
  )
{
#ifdef AUTH_KRB4
    /* VARIABLES */
    int rc;				/* return code holder */
    char *configname = 0;
    /* END VARIABLES */

    if (mech_option)
      configname = mech_option;
    else if (access(SASLAUTHD_CONF_FILE_DEFAULT, F_OK) == 0)
      configname = SASLAUTHD_CONF_FILE_DEFAULT;

    if (configname) {
      char complaint[1024];

      config = cfile_read(configname, complaint, sizeof(complaint));
      if (!config) {
	syslog(LOG_ERR, "auth_krb4_init %s", complaint);
	return -1;
      }
    }

    if (config) {
      srvtabname = cfile_getstring(config, "krb4_srvtab", srvtabname);
      verify_principal = cfile_getstring(config, "krb4_verify_principal",
					 verify_principal);
    }
    
    if (krbtf_init() == -1) {
      syslog(LOG_ERR, "auth_krb4_init krbtf_init failed");
      return -1;
    }

    rc = krb_get_lrealm(default_realm, 1);
    if (rc) {
	syslog(LOG_ERR, "auth_krb4: krb_get_lrealm: %s",
	       krb_get_err_text(rc));
	return -1;
    }

    if (gethostname(myhostname, sizeof(myhostname)) < 0) {
      syslog(LOG_ERR, "auth_krb4: gethoanem(): %m");
      return -1;
    }
    myhostname[sizeof(myhostname) - 1] = '\0';

    return 0;
#else /* ! AUTH_KRB4 */
    return -1;
#endif /* ! AUTH_KRB4 */
}
Exemple #9
0
static int
verify_pass(pam_handle_t *pamh,
	    const char *name,
	    const char *inst,
	    const char *pass)
{
  char realm[REALM_SZ];
  int ret, krb_verify, old_euid, old_ruid;

  krb_get_lrealm(realm, 1);
  if (ctrl_on(KRB4_NO_VERIFY))
    krb_verify = KRB_VERIFY_SECURE_FAIL;
  else
    krb_verify = KRB_VERIFY_SECURE;
  old_ruid = getuid();
  old_euid = geteuid();
  setreuid(0, 0);
  ret = krb_verify_user(name, inst, realm, pass, krb_verify, NULL);
  pdeb("krb_verify_user(`%s', `%s', `%s', pw, %d, NULL) returns %s",
       name, inst, realm, krb_verify,
       krb_get_err_text(ret));
  setreuid(old_ruid, old_euid);
  if (getuid() != old_ruid || geteuid() != old_euid)
    {
      psyslog(LOG_ALERT , "setreuid(%d, %d) failed at line %d",
	      old_ruid, old_euid, __LINE__);
      exit(1);
    }
    
  switch(ret) {
  case KSUCCESS:
    return PAM_SUCCESS;
  case KDC_PR_UNKNOWN:
    return PAM_USER_UNKNOWN;
  case SKDC_CANT:
  case SKDC_RETRY:
  case RD_AP_TIME:
    return PAM_AUTHINFO_UNAVAIL;
  default:
    return PAM_AUTH_ERR;
  }
}
Exemple #10
0
static int
krb4_decode(void *app_data, void *buf, int len, int level)
{
    MSG_DAT m;
    int e;
    struct krb4_data *d = app_data;
    
    if(level == prot_safe)
	e = krb_rd_safe(buf, len, &d->key,
			(struct sockaddr_in *)REMOTE_ADDR,
			(struct sockaddr_in *)LOCAL_ADDR, &m);
    else
	e = krb_rd_priv(buf, len, d->schedule, &d->key, 
			(struct sockaddr_in *)REMOTE_ADDR,
			(struct sockaddr_in *)LOCAL_ADDR, &m);
    if(e){
	ftp_err("krb4_decode: %s", krb_get_err_text(e));
	return -1;
    }
    memmove(buf, m.app_data, m.app_length);
    return m.app_length;
}
Exemple #11
0
static void
iterate (krb5_context context,
	 const char *database,
	 HDB *db,
	 int type,
	 struct prop_data *pd)
{
    int ret;

    switch(type) {
    case HPROP_KRB4_DUMP:
	ret = v4_prop_dump(pd, database);
	break;
#ifdef KRB4
    case HPROP_KRB4_DB:
	ret = kerb_db_iterate ((k_iter_proc_t)kdb_prop, pd);
	if(ret)
	    krb5_errx(context, 1, "kerb_db_iterate: %s", 
		      krb_get_err_text(ret));
	break;
#endif /* KRB4 */
    case HPROP_KASERVER:
	ret = ka_dump(pd, database);
	if(ret)
	    krb5_err(context, 1, ret, "ka_dump");
	break;
    case HPROP_MIT_DUMP:
	ret = mit_prop_dump(pd, database);
	if (ret)
	    krb5_errx(context, 1, "mit_prop_dump: %s",
		      krb5_get_err_text(context, ret));
	break;
    case HPROP_HEIMDAL:
	ret = hdb_foreach(context, db, HDB_F_DECRYPT, v5_prop, pd);
	if(ret)
	    krb5_err(context, 1, ret, "hdb_foreach");
	break;
    }
}
Exemple #12
0
static int
krb4_auth(void *app_data, char *host)
{
    int ret;
    char *p;
    int len;
    KTEXT_ST adat;
    MSG_DAT msg_data;
    int checksum;
    uint32_t cs;
    struct krb4_data *d = app_data;
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
    struct sockaddr_in *localaddr  = (struct sockaddr_in *)LOCAL_ADDR;
/*  struct sockaddr_in *remoteaddr = (struct sockaddr_in *)REMOTE_ADDR;*/
#endif

    checksum = getpid();
    ret = mk_auth(d, &adat, "ftp", host, checksum);
    if(ret == KDC_PR_UNKNOWN)
	ret = mk_auth(d, &adat, "rcmd", host, checksum);
    if(ret){
	printf("%s\n", krb_get_err_text(ret));
	return AUTH_CONTINUE;
    }

#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
    if (krb_get_config_bool("nat_in_use")) {
      struct in_addr natAddr;

      if (krb_get_our_ip_for_realm(krb_realmofhost(host),
				   &natAddr) != KSUCCESS
	  && krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
	ftp_err(_("Can't get address for realm %s\n"),
	       krb_realmofhost(host));
      else {
	if (natAddr.s_addr != localaddr->sin_addr.s_addr) {
	  ftp_err(_("Using NAT IP address (%s) for kerberos 4\n"),
		 inet_ntoa(natAddr));
	  localaddr->sin_addr = natAddr;
	}
      }
    }
#endif

   if(base64_encode(adat.dat, adat.length, &p) < 0) {
	ftp_err(_("Out of memory base64-encoding\n"));
	return AUTH_CONTINUE;
    }
    ret = ftp_cmd("ADAT %s", p);
    free(p);

    if(ftp->code != ctComplete){
	ftp_err(_("Server didn't accept auth data\n"));
	return AUTH_ERROR;
    }

    p = strstr(ftp->reply, "ADAT=");
    if(!p){
	ftp_err(_("Remote host didn't send adat reply\n"));
	return AUTH_ERROR;
    }
    p += 5;
    len = base64_decode(p, adat.dat);
    if(len < 0){
	ftp_err(_("Failed to decode base64 from server\n"));
	return AUTH_ERROR;
    }
    adat.length = len;
    ret = krb_rd_safe(adat.dat, adat.length, &d->key, 
		      (struct sockaddr_in *)hisctladdr, 
		      (struct sockaddr_in *)myctladdr, &msg_data);
    if(ret){
	ftp_err(_("Error reading reply from server: %s\n"),
	       krb_get_err_text(ret));
	return AUTH_ERROR;
    }
    krb_get_int(msg_data.app_data, &cs, 4, 0);
    if(cs - checksum != 1){
	ftp_err(_("Bad checksum returned from server\n"));
	return AUTH_ERROR;
    }
    return AUTH_OK;
}
Exemple #13
0
static int
krb4_auth(void *app_data, struct connectdata *conn)
{
  int ret;
  char *p;
  unsigned char *ptr;
  size_t len;
  KTEXT_ST adat;
  MSG_DAT msg_data;
  int checksum;
  u_int32_t cs;
  struct krb4_data *d = app_data;
  char *host = conn->host.name;
  ssize_t nread;
  int l = sizeof(conn->local_addr);
  struct SessionHandle *data = conn->data;
  CURLcode result;

  if(getsockname(conn->sock[FIRSTSOCKET],
                 (struct sockaddr *)LOCAL_ADDR, &l) < 0)
    perror("getsockname()");

  checksum = getpid();
  ret = mk_auth(d, &adat, "ftp", host, checksum);
  if(ret == KDC_PR_UNKNOWN)
    ret = mk_auth(d, &adat, "rcmd", host, checksum);
  if(ret) {
    infof(data, "%s\n", krb_get_err_text(ret));
    return AUTH_CONTINUE;
  }

#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
  if(krb_get_config_bool("nat_in_use")) {
    struct sockaddr_in *localaddr  = (struct sockaddr_in *)LOCAL_ADDR;
    struct in_addr natAddr;

    if(krb_get_our_ip_for_realm(krb_realmofhost(host),
                                 &natAddr) != KSUCCESS
        && krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
      infof(data, "Can't get address for realm %s\n",
                 krb_realmofhost(host));
    else {
      if(natAddr.s_addr != localaddr->sin_addr.s_addr) {
        char addr_buf[128];
        if(Curl_inet_ntop(AF_INET, natAddr, addr_buf, sizeof(addr_buf)))
          infof(data, "Using NAT IP address (%s) for kerberos 4\n", addr_buf);
        localaddr->sin_addr = natAddr;
      }
    }
  }
#endif

  if(Curl_base64_encode(conn->data, (char *)adat.dat, adat.length, &p) < 1) {
    Curl_failf(data, "Out of memory base64-encoding");
    return AUTH_CONTINUE;
  }

  result = Curl_ftpsendf(conn, "ADAT %s", p);

  free(p);

  if(result)
    return -2;

  if(Curl_GetFTPResponse(&nread, conn, NULL))
    return -1;

  if(data->state.buffer[0] != '2'){
    Curl_failf(data, "Server didn't accept auth data");
    return AUTH_ERROR;
  }

  p = strstr(data->state.buffer, "ADAT=");
  if(!p) {
    Curl_failf(data, "Remote host didn't send adat reply");
    return AUTH_ERROR;
  }
  p += 5;
  len = Curl_base64_decode(p, &ptr);
  if(len > sizeof(adat.dat)-1) {
    free(ptr);
    len=0;
  }
  if(!len || !ptr) {
    Curl_failf(data, "Failed to decode base64 from server");
    return AUTH_ERROR;
  }
  memcpy((char *)adat.dat, ptr, len);
  free(ptr);
  adat.length = len;
  ret = krb_rd_safe(adat.dat, adat.length, &d->key,
                    (struct sockaddr_in *)hisctladdr,
                    (struct sockaddr_in *)myctladdr, &msg_data);
  if(ret) {
    Curl_failf(data, "Error reading reply from server: %s",
               krb_get_err_text(ret));
    return AUTH_ERROR;
  }
  krb_get_int(msg_data.app_data, &cs, 4, 0);
  if(cs - checksum != 1) {
    Curl_failf(data, "Bad checksum returned from server");
    return AUTH_ERROR;
  }
  return AUTH_OK;
}
Exemple #14
0
static int
#if defined(USE_PAM) || defined(_AIX)
isNoPassAllowed( const char *un )
{
	struct passwd *pw = 0;
# ifdef HAVE_GETSPNAM /* (sic!) - not USESHADOW */
	struct spwd *spw;
# endif
#else
isNoPassAllowed( const char *un, struct passwd *pw )
{
#endif
	struct group *gr;
	char **fp;
	int hg;

	if (!*un)
		return 0;

	if (cursource != PWSRC_MANUAL)
		return 1;

	for (hg = 0, fp = td->noPassUsers; *fp; fp++)
		if (**fp == '@')
			hg = 1;
		else if (!strcmp( un, *fp ))
			return 1;
		else if (!strcmp( "*", *fp )) {
#if defined(USE_PAM) || defined(_AIX)
			if (!(pw = getpwnam( un )))
				return 0;
			if (pw->pw_passwd[0] == '!' || pw->pw_passwd[0] == '*')
				continue;
# ifdef HAVE_GETSPNAM /* (sic!) - not USESHADOW */
			if ((spw = getspnam( un )) &&
			    (spw->sp_pwdp[0] == '!' || spw->sp_pwdp[0] == '*'))
					continue;
# endif
#endif
			if (pw->pw_uid)
				return 1;
		}

#if defined(USE_PAM) || defined(_AIX)
	if (hg && (pw || (pw = getpwnam( un )))) {
#else
	if (hg) {
#endif
		for (setgrent(); (gr = getgrent()); )
			for (fp = td->noPassUsers; *fp; fp++)
				if (**fp == '@' && !strcmp( gr->gr_name, *fp + 1 )) {
					if (pw->pw_gid == gr->gr_gid) {
						endgrent();
						return 1;
					}
					for (; *gr->gr_mem; gr->gr_mem++)
						if (!strcmp( un, *gr->gr_mem )) {
							endgrent();
							return 1;
						}
				}
		endgrent();
	}

	return 0;
}

#if !defined(USE_PAM) && !defined(_AIX) && defined(HAVE_SETUSERCONTEXT)
# define LC_RET0 do { login_close(lc); return 0; } while(0)
#else
# define LC_RET0 return 0
#endif

int
verify( GConvFunc gconv, int rootok )
{
#ifdef USE_PAM
	const char *psrv;
	struct pam_data pdata;
	int pretc, pnopass;
	char psrvb[64];
#elif defined(_AIX)
	char *msg, *curret;
	int i, reenter;
#else
	struct stat st;
	const char *nolg;
	char *buf;
	int fd;
# ifdef HAVE_GETUSERSHELL
	char *s;
# endif
# if defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || defined(USESHADOW)
	int tim, expir, warntime, quietlog;
# endif
#endif

	debug( "verify ...\n" );

#ifdef USE_PAM

	pnopass = FALSE;
	if (!strcmp( curtype, "classic" )) {
		if (!gconv( GCONV_USER, 0 ))
			return 0;
		if (isNoPassAllowed( curuser )) {
			gconv( GCONV_PASS_ND, 0 );
			if (!*curpass) {
				pnopass = TRUE;
				sprintf( psrvb, "%.31s-np", PAMService );
				psrv = psrvb;
			} else
				psrv = PAMService;
		} else
			psrv = PAMService;
		pdata.usecur = TRUE;
	} else {
		sprintf( psrvb, "%.31s-%.31s", PAMService, curtype );
		psrv = psrvb;
		pdata.usecur = FALSE;
	}
	pdata.gconv = gconv;
	if (!doPAMAuth( psrv, &pdata ))
		return 0;

#elif defined(_AIX)

	if ((td->displayType & d_location) == dForeign) {
		char *tmpch;
		strncpy( hostname, td->name, sizeof(hostname) - 1 );
		hostname[sizeof(hostname)-1] = '\0';
		if ((tmpch = strchr( hostname, ':' )))
			*tmpch = '\0';
	} else
		hostname[0] = '\0';

	/* tty names should only be 15 characters long */
# if 0
	for (i = 0; i < 15 && td->name[i]; i++) {
		if (td->name[i] == ':' || td->name[i] == '.')
			tty[i] = '_';
		else
			tty[i] = td->name[i];
	}
	tty[i] = '\0';
# else
	memcpy( tty, "/dev/xdm/", 9 );
	for (i = 0; i < 6 && td->name[i]; i++) {
		if (td->name[i] == ':' || td->name[i] == '.')
			tty[9 + i] = '_';
		else
			tty[9 + i] = td->name[i];
	}
	tty[9 + i] = '\0';
# endif

	if (!strcmp( curtype, "classic" )) {
		if (!gconv( GCONV_USER, 0 ))
			return 0;
		if (isNoPassAllowed( curuser )) {
			gconv( GCONV_PASS_ND, 0 );
			if (!*curpass) {
				debug( "accepting despite empty password\n" );
				goto done;
			}
		} else
			if (!gconv( GCONV_PASS, 0 ))
				return 0;
		enduserdb();
		msg = NULL;
		if ((i = authenticate( curuser, curpass, &reenter, &msg ))) {
			debug( "authenticate() failed: %s\n", msg );
			if (msg)
				free( msg );
			loginfailed( curuser, hostname, tty );
			if (i == ENOENT || i == ESAD)
				V_RET_AUTH;
			else
				V_RET_FAIL( 0 );
		}
		if (reenter) {
			logError( "authenticate() requests more data: %s\n", msg );
			free( msg );
			V_RET_FAIL( 0 );
		}
	} else if (!strcmp( curtype, "generic" )) {
		if (!gconv( GCONV_USER, 0 ))
			return 0;
		for (curret = 0;;) {
			msg = NULL;
			if ((i = authenticate( curuser, curret, &reenter, &msg ))) {
				debug( "authenticate() failed: %s\n", msg );
				if (msg)
					free( msg );
				loginfailed( curuser, hostname, tty );
				if (i == ENOENT || i == ESAD)
					V_RET_AUTH;
				else
					V_RET_FAIL( 0 );
			}
			if (curret)
				free( curret );
			if (!reenter)
				break;
			if (!(curret = gconv( GCONV_HIDDEN, msg )))
				return 0;
			free( msg );
		}
	} else {
		logError( "Unsupported authentication type %\"s requested\n", curtype );
		V_RET_FAIL( 0 );
	}
	if (msg) {
		displayStr( V_MSG_INFO, msg );
		free( msg );
	}

  done:

#else

	if (strcmp( curtype, "classic" )) {
		logError( "Unsupported authentication type %\"s requested\n", curtype );
		V_RET_FAIL( 0 );
	}

	if (!gconv( GCONV_USER, 0 ))
		return 0;

	if (!(p = getpwnam( curuser ))) {
		debug( "getpwnam() failed.\n" );
		gconv( GCONV_PASS, 0 );
		V_RET_AUTH;
	}
	if (p->pw_passwd[0] == '!' || p->pw_passwd[0] == '*') {
		debug( "account is locked\n" );
		gconv( GCONV_PASS, 0 );
		V_RET_AUTH;
	}

# ifdef USESHADOW
	if ((sp = getspnam( curuser ))) {
		p->pw_passwd = sp->sp_pwdp;
		if (p->pw_passwd[0] == '!' || p->pw_passwd[0] == '*') {
			debug( "account is locked\n" );
			gconv( GCONV_PASS, 0 );
			V_RET_AUTH;
		}
	} else
		debug( "getspnam() failed: %m. Are you root?\n" );
# endif

	if (!*p->pw_passwd) {
		if (!td->allowNullPasswd) {
			debug( "denying user with empty password\n" );
			gconv( GCONV_PASS, 0 );
			V_RET_AUTH;
		}
		goto nplogin;
	}

	if (isNoPassAllowed( curuser, p )) {
	  nplogin:
		gconv( GCONV_PASS_ND, 0 );
		if (!*curpass) {
			debug( "accepting password-less login\n" );
			goto done;
		}
	} else
		if (!gconv( GCONV_PASS, 0 ))
			return 0;

# ifdef KERBEROS
	if (p->pw_uid) {
		int ret;
		char realm[REALM_SZ];

		if (krb_get_lrealm( realm, 1 )) {
			logError( "Cannot get KerberosIV realm.\n" );
			V_RET_FAIL( 0 );
		}

		sprintf( krbtkfile, "%s.%.*s", TKT_ROOT, MAXPATHLEN - strlen( TKT_ROOT ) - 2, td->name );
		krb_set_tkt_string( krbtkfile );
		unlink( krbtkfile );

		ret = krb_verify_user( curuser, "", realm, curpass, 1, "rcmd" );
		if (ret == KSUCCESS) {
			chown( krbtkfile, p->pw_uid, p->pw_gid );
			debug( "KerberosIV verify succeeded\n" );
			goto done;
		} else if (ret != KDC_PR_UNKNOWN && ret != SKDC_CANT) {
			logError( "KerberosIV verification failure %\"s for %s\n",
			          krb_get_err_text( ret ), curuser );
			krbtkfile[0] = '\0';
			V_RET_FAIL( 0 );
		}
		debug( "KerberosIV verify failed: %s\n", krb_get_err_text( ret ) );
	}
	krbtkfile[0] = '\0';
# endif	 /* KERBEROS */

# if defined(ultrix) || defined(__ultrix__)
	if (authenticate_user( p, curpass, NULL ) < 0)
# elif defined(HAVE_PW_ENCRYPT)
	if (strcmp( pw_encrypt( curpass, p->pw_passwd ), p->pw_passwd ))
# elif defined(HAVE_CRYPT)
	if (strcmp( crypt( curpass, p->pw_passwd ), p->pw_passwd ))
# else
	if (strcmp( curpass, p->pw_passwd ))
# endif
	{
		debug( "password verify failed\n" );
		V_RET_AUTH;
	}

  done:

#endif /* !defined(USE_PAM) && !defined(_AIX) */

	debug( "restrict %s ...\n", curuser );

#if defined(USE_PAM) || defined(_AIX)
	if (!(p = getpwnam( curuser ))) {
		logError( "getpwnam(%s) failed.\n", curuser );
		V_RET_FAIL( 0 );
	}
#endif
	if (!p->pw_uid) {
		if (!rootok && !td->allowRootLogin)
			V_RET_FAIL( "Root logins are not allowed" );
		return 1; /* don't deny root to log in */
	}

#ifdef USE_PAM

	debug( " pam_acct_mgmt() ...\n" );
	pretc = pam_acct_mgmt( pamh, 0 );
	reInitErrorLog();
	debug( " pam_acct_mgmt() returned: %s\n", pam_strerror( pamh, pretc ) );
	if (pretc == PAM_NEW_AUTHTOK_REQD) {
		pdata.usecur = FALSE;
		pdata.gconv = conv_interact;
		/* pam will have output a message already, so no prepareErrorGreet() */
		if (gconv != conv_interact || pnopass) {
			pam_end( pamh, PAM_SUCCESS );
			pamh = 0;
			gSendInt( V_CHTOK_AUTH );
			/* this cannot auth the wrong user, as only classic auths get here */
			while (!doPAMAuth( PAMService, &pdata ))
				if (pdata.abort)
					return 0;
			gSendInt( V_PRE_OK );
		} else
			gSendInt( V_CHTOK );
		for (;;) {
			debug( " pam_chauthtok() ...\n" );
			pretc = pam_chauthtok( pamh, PAM_CHANGE_EXPIRED_AUTHTOK );
			reInitErrorLog();
			debug( " pam_chauthtok() returned: %s\n", pam_strerror( pamh, pretc ) );
			if (pdata.abort) {
				pam_end( pamh, PAM_SUCCESS );
				pamh = 0;
				return 0;
			}
			if (pretc == PAM_SUCCESS)
				break;
			/* effectively there is only PAM_AUTHTOK_ERR */
			gSendInt( V_FAIL );
		}
		if (curpass)
			free( curpass );
		curpass = newpass;
		newpass = 0;
	} else if (pretc != PAM_SUCCESS) {
		pam_end( pamh, pretc );
		pamh = 0;
		V_RET_AUTH;
	}

#elif defined(_AIX) /* USE_PAM */

	msg = NULL;
	if (loginrestrictions( curuser,
	                       ((td->displayType & d_location) == dForeign) ? S_RLOGIN : S_LOGIN,
	                       tty, &msg ) == -1)
	{
		debug( "loginrestrictions() - %s\n", msg ? msg : "error" );
		loginfailed( curuser, hostname, tty );
		prepareErrorGreet();
		if (msg) {
			displayStr( V_MSG_ERR, msg );
			free( msg );
		}
		gSendInt( V_AUTH );
		return 0;
	}
	if (msg)
		free( (void *)msg );

#endif /* USE_PAM || _AIX */

#ifndef _AIX

# ifdef HAVE_SETUSERCONTEXT
#  ifdef HAVE_LOGIN_GETCLASS
	lc = login_getclass( p->pw_class );
#  else
	lc = login_getpwclass( p );
#  endif
	if (!lc)
		V_RET_FAIL( 0 );

	p->pw_shell = login_getcapstr( lc, "shell", p->pw_shell, p->pw_shell );
# endif

# ifndef USE_PAM

/* restrict_expired */
#  if defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || defined(USESHADOW)

#   if !defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || (!defined(HAVE_SETUSERCONTEXT) && defined(USESHADOW))
	if (sp)
#   endif
	{

#   define DEFAULT_WARN	(2L * 7L)  /* Two weeks */

		tim = time( NULL ) / 86400L;

#   ifdef HAVE_SETUSERCONTEXT
		quietlog = login_getcapbool( lc, "hushlogin", 0 );
		warntime = login_getcaptime( lc, "warnexpire",
		                             DEFAULT_WARN * 86400L,
		                             DEFAULT_WARN * 86400L ) / 86400L;
#   else
		quietlog = 0;
#    ifdef USESHADOW
		warntime = sp->sp_warn != -1 ? sp->sp_warn : DEFAULT_WARN;
#    else
		warntime = DEFAULT_WARN;
#    endif
#   endif

#   ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
		if (p->pw_expire) {
			expir = p->pw_expire / 86400L;
#   else
		if (sp->sp_expire != -1) {
			expir = sp->sp_expire;
#   endif
			if (tim > expir) {
				displayStr( V_MSG_ERR,
				            "Your account has expired;"
				            " please contact your system administrator" );
				gSendInt( V_FAIL );
				LC_RET0;
			} else if (tim > (expir - warntime) && !quietlog) {
				displayMsg( V_MSG_INFO,
				            "Warning: your account will expire in %d day(s)",
				            expir - tim );
			}
		}

#   ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
		if (p->pw_change) {
			expir = p->pw_change / 86400L;
#   else
		if (!sp->sp_lstchg) {
			displayStr( V_MSG_ERR,
			            "You are required to change your password immediately"
			            " (root enforced)" );
			/* XXX todo password change */
			gSendInt( V_FAIL );
			LC_RET0;
		} else if (sp->sp_max != -1) {
			expir = sp->sp_lstchg + sp->sp_max;
			if (sp->sp_inact != -1 && tim > expir + sp->sp_inact) {
				displayStr( V_MSG_ERR,
				            "Your account has expired;"
				            " please contact your system administrator" );
				gSendInt( V_FAIL );
				LC_RET0;
			}
#   endif
			if (tim > expir) {
				displayStr( V_MSG_ERR,
				            "You are required to change your password immediately"
				            " (password aged)" );
				/* XXX todo password change */
				gSendInt( V_FAIL );
				LC_RET0;
			} else if (tim > (expir - warntime) && !quietlog) {
				displayMsg( V_MSG_INFO,
				            "Warning: your password will expire in %d day(s)",
				            expir - tim );
			}
		}

	}

#  endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE || USESHADOW */

/* restrict_nologin */
#  ifndef _PATH_NOLOGIN
#   define _PATH_NOLOGIN "/etc/nologin"
#  endif

	if ((
#  ifdef HAVE_SETUSERCONTEXT
	     /* Do we ignore a nologin file? */
	     !login_getcapbool( lc, "ignorenologin", 0 )) &&
	    (!stat( (nolg = login_getcapstr( lc, "nologin", "", NULL )), &st ) ||
#  endif
		 !stat( (nolg = _PATH_NOLOGIN), &st )))
	{
		if (st.st_size && (fd = open( nolg, O_RDONLY )) >= 0) {
			if ((buf = Malloc( st.st_size + 1 ))) {
				if (read( fd, buf, st.st_size ) == st.st_size) {
					close( fd );
					buf[st.st_size] = 0;
					displayStr( V_MSG_ERR, buf );
					free( buf );
					gSendInt( V_FAIL );
					LC_RET0;
				}
				free( buf );
			}
			close( fd );
		}
		displayStr( V_MSG_ERR,
		            "Logins are not allowed at the moment.\nTry again later" );
		gSendInt( V_FAIL );
		LC_RET0;
	}

/* restrict_time */
#  if defined(HAVE_SETUSERCONTEXT) && defined(HAVE_AUTH_TIMEOK)
	if (!auth_timeok( lc, time( NULL ) )) {
		displayStr( V_MSG_ERR,
		            "You are not allowed to login at the moment" );
		gSendInt( V_FAIL );
		LC_RET0;
	}
#  endif

#  ifdef HAVE_GETUSERSHELL
	for (;;) {
		if (!(s = getusershell())) {
			debug( "shell not in /etc/shells\n" );
			endusershell();
			V_RET_FAIL( "Your login shell is not listed in /etc/shells" );
		}
		if (!strcmp( s, p->pw_shell )) {
			endusershell();
			break;
		}
	}
#  endif

# endif /* !USE_PAM */

/* restrict_nohome */
# ifdef HAVE_SETUSERCONTEXT
	if (login_getcapbool( lc, "requirehome", 0 )) {
		struct stat st;
		if (!*p->pw_dir || stat( p->pw_dir, &st ) || st.st_uid != p->pw_uid) {
			displayStr( V_MSG_ERR, "Home folder not available" );
			gSendInt( V_FAIL );
			LC_RET0;
		}
	}
# endif

#endif /* !_AIX */

	return 1;

}


static const char *envvars[] = {
	"TZ", /* SYSV and SVR4, but never hurts */
#ifdef _AIX
	"AUTHSTATE", /* for kerberos */
#endif
	NULL
};


#if defined(USE_PAM) && defined(HAVE_INITGROUPS)
static int num_saved_gids;
static gid_t *saved_gids;

static int
saveGids( void )
{
	num_saved_gids = getgroups( 0, 0 );
	if (!(saved_gids = Malloc( sizeof(gid_t) * num_saved_gids )))
		return 0;
	if (getgroups( num_saved_gids, saved_gids ) < 0) {
		logError( "saving groups failed: %m\n" );
		return 0;
	}
	return 1;
}

static int
restoreGids( void )
{
	if (setgroups( num_saved_gids, saved_gids ) < 0) {
		logError( "restoring groups failed: %m\n" );
		return 0;
	}
	if (setgid( p->pw_gid ) < 0) {
		logError( "restoring gid failed: %m\n" );
		return 0;
	}
	return 1;
}
#endif /* USE_PAM && HAVE_INITGROUPS */

static int
resetGids( void )
{
#ifdef HAVE_INITGROUPS
	if (setgroups( 0, &p->pw_gid /* anything */ ) < 0) {
		logError( "restoring groups failed: %m\n" );
		return 0;
	}
#endif
	if (setgid( 0 ) < 0) {
		logError( "restoring gid failed: %m\n" );
		return 0;
	}
	return 1;
}

static int
setGid( const char *name, int gid )
{
	if (setgid( gid ) < 0) {
		logError( "setgid(%d) (user %s) failed: %m\n", gid, name );
		return 0;
	}
#ifdef HAVE_INITGROUPS
	if (initgroups( name, gid ) < 0) {
		logError( "initgroups for %s failed: %m\n", name );
		setgid( 0 );
		return 0;
	}
#endif	 /* QNX4 doesn't support multi-groups, no initgroups() */
	return 1;
}

static int
setUid( const char *name, int uid )
{
	if (setuid( uid ) < 0) {
		logError( "setuid(%d) (user %s) failed: %m\n", uid, name );
		return 0;
	}
	return 1;
}

static int
setUser( const char *name, int uid, int gid )
{
	if (setGid( name, gid )) {
		if (setUid( name, uid ))
			return 1;
		resetGids();
	}
	return 0;
}

#if defined(SECURE_RPC) || defined(K5AUTH)
static void
nukeAuth( int len, const char *name )
{
	int i;

	for (i = 0; i < td->authNum; i++)
		if (td->authorizations[i]->name_length == len &&
		    !memcmp( td->authorizations[i]->name, name, len ))
		{
			memcpy( &td->authorizations[i], &td->authorizations[i+1],
			        sizeof(td->authorizations[i]) * (--td->authNum - i) );
			break;
		}
}
#endif

static void
mergeSessionArgs( int cansave )
{
	char *mfname;
	const char *fname;
	int i, needsave;

	mfname = 0;
	fname = ".dmrc";
	if ((!curdmrc || newdmrc) && *dmrcDir)
		if (strApp( &mfname, dmrcDir, "/", curuser, fname, (char *)0 ))
			fname = mfname;
	needsave = 0;
	if (!curdmrc) {
		curdmrc = iniLoad( fname );
		if (!curdmrc) {
			strDup( &curdmrc, "[Desktop]\nSession=default\n" );
			needsave = 1;
		}
	}
	if (newdmrc) {
		curdmrc = iniMerge( curdmrc, newdmrc );
		needsave = 1;
	}
	if (needsave && cansave)
		if (!iniSave( curdmrc, fname ) && errno == ENOENT && mfname) {
			for (i = 0; mfname[i]; i++)
				if (mfname[i] == '/') {
					mfname[i] = 0;
					mkdir( mfname, 0755 );
					mfname[i] = '/';
				}
			iniSave( curdmrc, mfname );
		}
	if (mfname)
		free( mfname );
}

static int
createClientLog( const char *log )
{
	char randstr[32], *randstrp = 0, *lname;
	int lfd;

	for (;;) {
		struct expando macros[] = {
			{ 'd', 0, td->name },
			{ 'u', 0, curuser },
			{ 'r', 0, randstrp },
			{ 0, 0, 0 }
		};
		if (!(lname = expandMacros( log, macros )))
			exit( 1 );
		unlink( lname );
		if ((lfd = open( lname, O_WRONLY|O_CREAT|O_EXCL, 0600 )) >= 0) {
			dup2( lfd, 1 );
			dup2( lfd, 2 );
			close( lfd );
			free( lname );
			return TRUE;
		}
		if (errno != EEXIST || !macros[2].uses) {
			free( lname );
			return FALSE;
		}
		logInfo( "Session log file %s not usable, trying another one.\n",
		         lname );
		free( lname );
		sprintf( randstr, "%d", secureRandom() );
		randstrp = randstr;
	}
}
Exemple #15
0
int
startClient( volatile int *pid )
{
	const char *home, *sessargs, *desksess;
	char **env, *xma;
	char **argv, *fname, *str;
#ifdef USE_PAM
	char ** volatile pam_env;
# ifndef HAVE_PAM_GETENVLIST
	char **saved_env;
# endif
	int pretc;
#else
# ifdef _AIX
	char *msg;
	char **theenv;
	extern char **newenv; /* from libs.a, this is set up by setpenv */
# endif
#endif
#ifdef HAVE_SETUSERCONTEXT
	extern char **environ;
#endif
	char *failsafeArgv[2];
	char *buf, *buf2;
	int i;

	if (strCmp( dmrcuser, curuser )) {
		if (curdmrc) { free( curdmrc ); curdmrc = 0; }
		if (dmrcuser) { free( dmrcuser ); dmrcuser = 0; }
	}

#if defined(USE_PAM) || defined(_AIX)
	if (!(p = getpwnam( curuser ))) {
		logError( "getpwnam(%s) failed.\n", curuser );
	  pError:
		displayStr( V_MSG_ERR, 0 );
		return 0;
	}
#endif

#ifndef USE_PAM
# ifdef _AIX
	msg = NULL;
	loginsuccess( curuser, hostname, tty, &msg );
	if (msg) {
		debug( "loginsuccess() - %s\n", msg );
		free( (void *)msg );
	}
# else /* _AIX */
#  if defined(KERBEROS) && defined(AFS)
	if (krbtkfile[0] != '\0') {
		if (k_hasafs()) {
			int fail = 0;
			if (k_setpag() == -1) {
				logError( "setpag() for %s failed\n", curuser );
				fail = 1;
			}
			if ((ret = k_afsklog( NULL, NULL )) != KSUCCESS) {
				logError( "AFS Warning: %s\n", krb_get_err_text( ret ) );
				fail = 1;
			}
			if (fail)
				displayMsg( V_MSG_ERR,
				            "Warning: Problems during Kerberos4/AFS setup." );
		}
	}
#  endif /* KERBEROS && AFS */
# endif /* _AIX */
#endif	/* !PAM */

	curuid = p->pw_uid;
	curgid = p->pw_gid;

	env = baseEnv( curuser );
	xma = 0;
	strApp( &xma, "method=", curtype, (char *)0 );
	if (td_setup)
		strApp( &xma, ",auto", (char *)0 );
	if (xma) {
		env = setEnv( env, "XDM_MANAGED", xma );
		free( xma );
	}
	if (td->autoLock && cursource == PWSRC_AUTOLOGIN)
		env = setEnv( env, "DESKTOP_LOCKED", "true" );
	env = setEnv( env, "PATH", curuid ? td->userPath : td->systemPath );
	env = setEnv( env, "SHELL", p->pw_shell );
	env = setEnv( env, "HOME", p->pw_dir );
#if !defined(USE_PAM) && !defined(_AIX) && defined(KERBEROS)
	if (krbtkfile[0] != '\0')
		env = setEnv( env, "KRBTKFILE", krbtkfile );
#endif
	userEnviron = inheritEnv( env, envvars );
	env = systemEnv( curuser );
	systemEnviron = setEnv( env, "HOME", p->pw_dir );
	debug( "user environment:\n%[|''>'\n's"
	       "system environment:\n%[|''>'\n's"
	       "end of environments\n",
	       userEnviron,
	       systemEnviron );

	/*
	 * for user-based authorization schemes,
	 * add the user to the server's allowed "hosts" list.
	 */
	for (i = 0; i < td->authNum; i++) {
#ifdef SECURE_RPC
		if (td->authorizations[i]->name_length == 9 &&
		    !memcmp( td->authorizations[i]->name, "SUN-DES-1", 9 ))
		{
			XHostAddress addr;
			char netname[MAXNETNAMELEN+1];
			char domainname[MAXNETNAMELEN+1];

			getdomainname( domainname, sizeof(domainname) );
			user2netname( netname, curuid, domainname );
			addr.family = FamilyNetname;
			addr.length = strlen( netname );
			addr.address = netname;
			XAddHost( dpy, &addr );
		}
#endif
#ifdef K5AUTH
		if (td->authorizations[i]->name_length == 14 &&
		    !memcmp( td->authorizations[i]->name, "MIT-KERBEROS-5", 14 ))
		{
			/* Update server's auth file with user-specific info.
			 * Don't need to AddHost because X server will do that
			 * automatically when it reads the cache we are about
			 * to point it at.
			 */
			XauDisposeAuth( td->authorizations[i] );
			td->authorizations[i] =
				krb5GetAuthFor( 14, "MIT-KERBEROS-5", td->name );
			saveServerAuthorizations( td, td->authorizations, td->authNum );
		}
#endif
	}

	if (*dmrcDir)
		mergeSessionArgs( TRUE );

	debug( "now starting the session\n" );

#ifdef USE_PAM

# ifdef HAVE_SETUSERCONTEXT
	if (setusercontext( lc, p, p->pw_uid, LOGIN_SETGROUP )) {
		logError( "setusercontext(groups) for %s failed: %m\n",
		          curuser );
		goto pError;
	}
# else
	if (!setGid( curuser, curgid ))
		goto pError;
# endif

# ifndef HAVE_PAM_GETENVLIST
	if (!(pam_env = initStrArr( 0 ))) {
		resetGids();
		goto pError;
	}
	saved_env = environ;
	environ = pam_env;
# endif
	removeCreds = 1; /* set it first - i don't trust PAM's rollback */
	pretc = pam_setcred( pamh, 0 );
	reInitErrorLog();
# ifndef HAVE_PAM_GETENVLIST
	pam_env = environ;
	environ = saved_env;
# endif
# ifdef HAVE_INITGROUPS
	/* This seems to be a strange place for it, but do it:
	   - after the initial groups are set
	   - after pam_setcred might have set something, even in the error case
	   - before pam_setcred(DELETE_CRED) might need it
	 */
	if (!saveGids())
		goto pError;
# endif
	if (pretc != PAM_SUCCESS) {
		logError( "pam_setcred() for %s failed: %s\n",
		          curuser, pam_strerror( pamh, pretc ) );
		resetGids();
		return 0;
	}

	removeSession = 1; /* set it first - same as above */
	pretc = pam_open_session( pamh, 0 );
	reInitErrorLog();
	if (pretc != PAM_SUCCESS) {
		logError( "pam_open_session() for %s failed: %s\n",
		          curuser, pam_strerror( pamh, pretc ) );
		resetGids();
		return 0;
	}

	/* we don't want sessreg and the startup/reset scripts run with user
	   credentials. unfortunately, we can reset only the gids. */
	resetGids();

# define D_LOGIN_SETGROUP LOGIN_SETGROUP
#else /* USE_PAM */
# define D_LOGIN_SETGROUP 0
#endif /* USE_PAM */

	removeAuth = 1;
	chownCtrl( &td->ctrl, curuid );
	endpwent();
#if !defined(USE_PAM) && defined(USESHADOW) && !defined(_AIX)
	endspent();
#endif
	ctltalk.pipe = &ctlpipe;
	ASPrintf( &buf, "sub-daemon for display %s", td->name );
	ASPrintf( &buf2, "client for display %s", td->name );
	switch (gFork( &ctlpipe, buf, buf2, 0, 0, mstrtalk.pipe, pid )) {
	case 0:

		gCloseOnExec( ctltalk.pipe );
		if (Setjmp( ctltalk.errjmp ))
			exit( 1 );

		gCloseOnExec( mstrtalk.pipe );
		if (Setjmp( mstrtalk.errjmp ))
			goto cError;

#ifndef NOXDMTITLE
		setproctitle( "%s'", td->name );
#endif
		strApp( &prog, " '", (char *)0 );
		reInitErrorLog();

		setsid();

		sessreg( td, getpid(), curuser, curuid );

		/* We do this here, as we want to have the session as parent. */
		switch (source( systemEnviron, td->startup, td_setup )) {
		case 0:
			break;
		case wcCompose( 0, 0, 127 ):
			goto cError;
		default: /* Explicit failure => message already displayed. */
			logError( "Startup script returned non-zero exit code\n" );
			exit( 1 );
		}

	/* Memory leaks are ok here as we exec() soon. */

#if defined(USE_PAM) || !defined(_AIX)

# ifdef USE_PAM
		/* pass in environment variables set by libpam and modules it called */
#  ifdef HAVE_PAM_GETENVLIST
		pam_env = pam_getenvlist( pamh );
		reInitErrorLog();
#  endif
		if (pam_env)
			for (; *pam_env; pam_env++)
				userEnviron = putEnv( *pam_env, userEnviron );
# endif

# ifdef HAVE_SETLOGIN
		if (setlogin( curuser ) < 0) {
			logError( "setlogin for %s failed: %m\n", curuser );
			goto cError;
		}
#  define D_LOGIN_SETLOGIN LOGIN_SETLOGIN
# else
#  define D_LOGIN_SETLOGIN 0
# endif

# if defined(USE_PAM) && defined(HAVE_INITGROUPS)
		if (!restoreGids())
			goto cError;
# endif

# ifndef HAVE_SETUSERCONTEXT

#  ifdef USE_PAM
		if (!setUid( curuser, curuid ))
			goto cError;
#  else
		if (!setUser( curuser, curuid, curgid ))
			goto cError;
#  endif

# else /* !HAVE_SETUSERCONTEXT */

		/*
		 * Destroy environment.
		 * We need to do this before setusercontext() because that may
		 * set or reset some environment variables.
		 */
		if (!(environ = initStrArr( 0 )))
			goto cError;

		/*
		 * Set the user's credentials: uid, gid, groups,
		 * environment variables, resource limits, and umask.
		 */
		if (setusercontext( lc, p, p->pw_uid,
		        LOGIN_SETALL & ~(D_LOGIN_SETGROUP|D_LOGIN_SETLOGIN) ) < 0)
		{
			logError( "setusercontext for %s failed: %m\n", curuser );
			goto cError;
		}

		for (i = 0; environ[i]; i++)
			userEnviron = putEnv( environ[i], userEnviron );

# endif /* !HAVE_SETUSERCONTEXT */

#else /* PAM || !_AIX */
		/*
		 * Set the user's credentials: uid, gid, groups,
		 * audit classes, user limits, and umask.
		 */
		if (setpcred( curuser, NULL ) == -1) {
			logError( "setpcred for %s failed: %m\n", curuser );
			goto cError;
		}

		/*
		 * Set the users process environment. Store protected variables and
		 * obtain updated user environment list. This call will initialize
		 * global 'newenv'.
		 */
		if (setpenv( curuser, PENV_INIT | PENV_ARGV | PENV_NOEXEC,
		             userEnviron, NULL ) != 0)
		{
			logError( "Cannot set %s's process environment\n", curuser );
			goto cError;
		}
		userEnviron = newenv;

#endif /* _AIX */

		/*
		 * for user-based authorization schemes,
		 * use the password to get the user's credentials.
		 */
#ifdef SECURE_RPC
		/* do like "keylogin" program */
		if (!curpass[0])
			logInfo( "No password for NIS provided.\n" );
		else {
			char netname[MAXNETNAMELEN+1], secretkey[HEXKEYBYTES+1];
			int nameret, keyret;
			int len;
			int key_set_ok = 0;
			struct key_netstarg netst;

			nameret = getnetname( netname );
			debug( "user netname: %s\n", netname );
			len = strlen( curpass );
			if (len > 8)
				bzero( curpass + 8, len - 8 );
			keyret = getsecretkey( netname, secretkey, curpass );
			debug( "getsecretkey returns %d, key length %d\n",
			       keyret, strlen( secretkey ) );
			netst.st_netname = netname;
			memcpy( netst.st_priv_key, secretkey, HEXKEYBYTES );
			memset( netst.st_pub_key, 0, HEXKEYBYTES );
			if (key_setnet( &netst ) < 0)
				debug( "Could not set secret key.\n" );
			/* is there a key, and do we have the right password? */
			if (keyret == 1) {
				if (*secretkey) {
					keyret = key_setsecret( secretkey );
					debug( "key_setsecret returns %d\n", keyret );
					if (keyret == -1)
						logError( "Failed to set NIS secret key\n" );
					else
						key_set_ok = 1;
				} else {
					/* found a key, but couldn't interpret it */
					logError( "Password incorrect for NIS principal %s\n",
					          nameret ? netname : curuser );
				}
			}
			if (!key_set_ok)
				nukeAuth( 9, "SUN-DES-1" );
			bzero( secretkey, strlen( secretkey ) );
		}
#endif
#ifdef K5AUTH
		/* do like "kinit" program */
		if (!curpass[0])
			logInfo( "No password for Kerberos5 provided.\n" );
		else
			if ((str = krb5Init( curuser, curpass, td->name )))
				userEnviron = setEnv( userEnviron, "KRB5CCNAME", str );
			else
				nukeAuth( 14, "MIT-KERBEROS-5" );
#endif /* K5AUTH */
		if (td->autoReLogin) {
			gSet( &mstrtalk );
			gSendInt( D_ReLogin );
			gSendStr( curuser );
			gSendStr( curpass );
			gSendStr( newdmrc );
		}
		if (curpass)
			bzero( curpass, strlen( curpass ) );
		setUserAuthorization( td );
		home = getEnv( userEnviron, "HOME" );
		if (home && chdir( home ) < 0) {
			logError( "Cannot chdir to %s's home %s: %m\n", curuser, home );
			sendStr( V_MSG_ERR, "Cannot enter home directory. Using /.\n" );
			chdir( "/" );
			userEnviron = setEnv( userEnviron, "HOME", "/" );
			home = 0;
		}
		if (home || td->clientLogFile[0] == '/') {
			if (!createClientLog( td->clientLogFile )) {
				logWarn( "Session log file according to %s cannot be created: %m\n",
				         td->clientLogFile );
				goto tmperr;
			}
		} else {
		  tmperr:
			if (!createClientLog( td->clientLogFallback ))
				logError( "Fallback session log file according to %s cannot be created: %m\n",
				          td->clientLogFallback );
			/* Could inform the user, but I guess this is only confusing. */
		}
		if (!*dmrcDir)
			mergeSessionArgs( home != 0 );
		if (!(desksess = iniEntry( curdmrc, "Desktop", "Session", 0 )))
			desksess = "failsafe"; /* only due to OOM */
		gSet( &mstrtalk );
		gSendInt( D_User );
		gSendInt( curuid );
		gSendStr( curuser );
		gSendStr( desksess );
		close( mstrtalk.pipe->fd.w );
		userEnviron = setEnv( userEnviron, "DESKTOP_SESSION", desksess );
		for (i = 0; td->sessionsDirs[i]; i++) {
			fname = 0;
			if (strApp( &fname, td->sessionsDirs[i], "/", desksess, ".desktop", (char *)0 )) {
				if ((str = iniLoad( fname ))) {
					if (!strCmp( iniEntry( str, "Desktop Entry", "Hidden", 0 ), "true" ) ||
					    !(sessargs = iniEntry( str, "Desktop Entry", "Exec", 0 )))
						sessargs = "";
					free( str );
					free( fname );
					goto gotit;
				}
				free( fname );
			}
		}
		if (!strcmp( desksess, "failsafe" ) ||
		    !strcmp( desksess, "default" ) ||
		    !strcmp( desksess, "custom" ))
			sessargs = desksess;
		else
			sessargs = "";
	  gotit:
		if (!(argv = parseArgs( (char **)0, td->session )) ||
		    !(argv = addStrArr( argv, sessargs, -1 )))
			exit( 1 );
		if (argv[0] && *argv[0]) {
			debug( "executing session %\"[s\n", argv );
			execute( argv, userEnviron );
			logError( "Session %\"s execution failed: %m\n", argv[0] );
		} else
			logError( "Session has no command/arguments\n" );
		failsafeArgv[0] = td->failsafeClient;
		failsafeArgv[1] = 0;
		execute( failsafeArgv, userEnviron );
		logError( "Failsafe client %\"s execution failed: %m\n",
		          failsafeArgv[0] );
	  cError:
		sendStr( V_MSG_ERR, 0 );
		exit( 1 );
	case -1:
		free( buf );
		return 0;
	}
	debug( "StartSession, fork succeeded %d\n", *pid );
	free( buf );

	gSet( &ctltalk );
	if (!Setjmp( ctltalk.errjmp ))
		while (gRecvCmd( &i )) {
			buf = gRecvStr();
			displayStr( i, buf );
			free( buf );
			gSet( &ctltalk );
			gSendInt( 0 );
		}
	gClosen( ctltalk.pipe );
	finishGreet();

	return 1;
}
Exemple #16
0
char *					/* R: allocated response string */
auth_krb4 (
  /* PARAMETERS */
  const char *login,			/* I: plaintext authenticator */
  const char *password,			/* I: plaintext password */
  const char *service,
  const char *realm_in
  /* END PARAMETERS */
  )
{
    /* VARIABLES */
    char aname[ANAME_SZ];		/* Kerberos principal */
    const char *realm;		        /* Kerberos realm to authenticate in */
    int rc;				/* return code */
    char tf_name[TF_NAME_LEN];		/* Ticket file name */
    char *instance, *user_specified;
    KTEXT_ST ticket;
    AUTH_DAT kdata;
    /* END VARIABLES */

    /*
     * Make sure we have a password. If this is NULL the call
     * to krb_get_pw_in_tkt below would try to prompt for
     * one interactively.
     */
    if (password == NULL) {
	syslog(LOG_ERR, "auth_krb4: NULL password?");
	return strdup("NO saslauthd internal error");
    }

    if (krbtf_name(tf_name, sizeof(tf_name)) != 0) {
      syslog(LOG_ERR, "auth_krb4: could not generate ticket file name");
      return strdup("NO saslauthd internal error");
    }
    krb_set_tkt_string(tf_name);

    strncpy(aname, login, ANAME_SZ-1);
    aname[ANAME_SZ-1] = '\0';

    instance = "";

    if (config) {
      char keyname[1024];

      snprintf(keyname, sizeof(keyname), "krb4_%s_instance", service);
      instance = cfile_getstring(config, keyname, "");
    }

    user_specified = strchr(aname, '.');
    if (user_specified) {
      if (instance && instance[0]) {
	/* sysadmin specified a (mandatory) instance */
	if (strcmp(user_specified + 1, instance)) {
	  return strdup("NO saslauthd principal name error");
	}
	/* nuke instance from "aname"-- matches what's already in "instance" */
	*user_specified = '\0';
      } else {
	/* sysadmin has no preference, so we shift
	 * instance name from "aname" to "instance"
	 */
	*user_specified = '\0';
	instance = user_specified + 1;
      }
    }

    if(realm_in && *realm_in != '\0') {
	realm = realm_in;
    } else {
	realm = default_realm;
    }

    rc = krb_get_pw_in_tkt(aname, instance, realm,
			   KRB_TICKET_GRANTING_TICKET,
			   realm, 1, password);

    if (rc == INTK_BADPW || rc == KDC_PR_UNKNOWN) {
	return strdup("NO");
    } else if (rc != KSUCCESS) {
      syslog(LOG_ERR, "ERROR: auth_krb4: krb_get_pw_in_tkt: %s",
	     krb_get_err_text(rc));

      return strdup("NO saslauthd internal error");
    }

    /* if the TGT wasn't spoofed, it should entitle us to an rcmd ticket... */
    rc = krb_mk_req(&ticket, verify_principal, myhostname, default_realm, 0);

    if (rc != KSUCCESS) {
      syslog(LOG_ERR, "ERROR: auth_krb4: krb_get_pw_in_tkt: %s",
	     krb_get_err_text(rc));
      dest_tkt();
      return strdup("NO saslauthd internal error");
    }

    /* .. and that ticket should match our secret host key */
    rc = krb_rd_req(&ticket, verify_principal, myhostname, 0, &kdata, srvtabname);

    if (rc != RD_AP_OK) {
      syslog(LOG_ERR, "ERROR: auth_krb4: krb_rd_req:%s",
	     krb_get_err_text(rc));
      dest_tkt();
      return strdup("NO saslauthd internal error");
    }

    dest_tkt();

    return strdup("OK");
}
Exemple #17
0
void
kerberos4_is(Authenticator *ap, unsigned char *data, int cnt)
{
    struct sockaddr_in addr;
    char realm[REALM_SZ];
    char instance[INST_SZ];
    int r;
    int addr_len;

    if (cnt-- < 1)
	return;
    switch (*data++) {
    case KRB_AUTH:
	if (krb_get_lrealm(realm, 1) != KSUCCESS) {
	    Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("No local realm\r\n");
	    return;
	}
	memmove(auth.dat, data, auth.length = cnt);
	if (auth_debug_mode) {
	    printf("Got %d bytes of authentication data\r\n", cnt);
	    printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
	    printd(auth.dat, auth.length);
	    printf("\r\n");
	}
	k_getsockinst(0, instance, sizeof(instance));
	addr_len = sizeof(addr);
	if(getpeername(0, (struct sockaddr *)&addr, &addr_len) < 0) {
	    if(auth_debug_mode)
		printf("getpeername failed\r\n");
	    Data(ap, KRB_REJECT, "getpeername failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    return;
	}
	r = krb_rd_req(&auth, KRB_SERVICE_NAME,
		       instance, addr.sin_addr.s_addr, &adat, "");
	if (r) {
	    if (auth_debug_mode)
		printf("Kerberos failed him as %s\r\n", name);
	    Data(ap, KRB_REJECT, (void *)krb_get_err_text(r), -1);
	    auth_finished(ap, AUTH_REJECT);
	    return;
	}
	/* save the session key */
	memmove(session_key, adat.session, sizeof(adat.session));
	krb_kntoln(&adat, name);

	if (UserNameRequested && !kuserok(&adat, UserNameRequested)){
	    char ts[MAXPATHLEN];
	    struct passwd *pw = getpwnam(UserNameRequested);

	    if(pw){
		snprintf(ts, sizeof(ts),
			 "%s%u",
			 TKT_ROOT,
			 (unsigned)pw->pw_uid);
		setenv("KRBTKFILE", ts, 1);
	    }
	    Data(ap, KRB_ACCEPT, NULL, 0);
	} else {
	    char *msg;

	    asprintf (&msg, "user `%s' is not authorized to "
		      "login as `%s'", 
		      krb_unparse_name_long(adat.pname, 
					    adat.pinst, 
					    adat.prealm), 
		      UserNameRequested ? UserNameRequested : "<nobody>");
	    if (msg == NULL)
		Data(ap, KRB_REJECT, NULL, 0);
	    else {
		Data(ap, KRB_REJECT, (void *)msg, -1);
		free(msg);
	    }
	}
	auth_finished(ap, AUTH_USER);
	break;
	
    case KRB_CHALLENGE:
#ifndef ENCRYPTION
	Data(ap, KRB_RESPONSE, NULL, 0);
#else
	if(!VALIDKEY(session_key)){
	    Data(ap, KRB_RESPONSE, NULL, 0);
	    break;
	}
	des_key_sched(&session_key, sched);
	{
	    des_cblock d_block;
	    int i;
	    Session_Key skey;

	    memmove(d_block, data, sizeof(d_block));

	    /* make a session key for encryption */
	    des_ecb_encrypt(&d_block, &session_key, sched, 1);
	    skey.type=SK_DES;
	    skey.length=8;
	    skey.data=session_key;
	    encrypt_session_key(&skey, 1);

	    /* decrypt challenge, add one and encrypt it */
	    des_ecb_encrypt(&d_block, &challenge, sched, 0);
	    for (i = 7; i >= 0; i--)
		if(++challenge[i] != 0)
		    break;
	    des_ecb_encrypt(&challenge, &challenge, sched, 1);
	    Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge));
	}
#endif
	break;

    case KRB_FORWARD:
	{
	    des_key_schedule ks;
	    unsigned char netcred[sizeof(CREDENTIALS)];
	    CREDENTIALS cred;
	    int ret;
	    if(cnt > sizeof(cred))
		abort();

	    des_set_key(&session_key, ks);
	    des_pcbc_encrypt((void*)data, (void*)netcred, cnt, 
			     ks, &session_key, DES_DECRYPT);
	    unpack_cred(netcred, cnt, &cred);
	    {
		if(strcmp(cred.service, KRB_TICKET_GRANTING_TICKET) ||
		   strncmp(cred.instance, cred.realm, sizeof(cred.instance)) ||
		   cred.lifetime < 0 || cred.lifetime > 255 ||
		   cred.kvno < 0 || cred.kvno > 255 ||
		   cred.issue_date < 0 || 
		   cred.issue_date > time(0) + CLOCK_SKEW ||
		   strncmp(cred.pname, adat.pname, sizeof(cred.pname)) ||
		   strncmp(cred.pinst, adat.pinst, sizeof(cred.pname))){
		    Data(ap, KRB_FORWARD_REJECT, "Bad credentials", -1);
		}else{
		    if((ret = tf_setup(&cred,
				       cred.pname,
				       cred.pinst)) == KSUCCESS){
		        struct passwd *pw = getpwnam(UserNameRequested);

			if (pw)
			  chown(tkt_string(), pw->pw_uid, pw->pw_gid);
			Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
		    } else{
			Data(ap, KRB_FORWARD_REJECT, 
			     krb_get_err_text(ret), -1);
		    }
		}
	    }
	    memset(data, 0, cnt);
	    memset(ks, 0, sizeof(ks));
	    memset(&cred, 0, sizeof(cred));
	}
	
	break;

    default:
	if (auth_debug_mode)
	    printf("Unknown Kerberos option %d\r\n", data[-1]);
	Data(ap, KRB_REJECT, 0, 0);
	break;
    }
}
Exemple #18
0
void
kerberos_v4(struct sockaddr_in *client, KTEXT pkt)
{
    static KTEXT_ST rpkt_st;
    KTEXT   rpkt = &rpkt_st;
    static KTEXT_ST ciph_st;
    KTEXT   ciph = &ciph_st;
    static KTEXT_ST tk_st;
    KTEXT   tk = &tk_st;
    static KTEXT_ST auth_st;
    KTEXT   auth = &auth_st;
    AUTH_DAT ad_st;
    AUTH_DAT *ad = &ad_st;


    static struct in_addr client_host;
    static int msg_byte_order;
    static int swap_bytes;
    static u_char k_flags;
 /* char   *p_name, *instance; */
    int     lifetime = 0;
    int     i;
    C_Block key;
    Key_schedule key_s;
    char   *ptr;

    krb5_keyblock k5key;
    krb5_kvno kvno;
    krb5_deltat sk5life, ck5life;
    KRB4_32 v4endtime, v4req_end;

    k5key.contents = NULL;	/* in case we have to free it */

    ciph->length = 0;

    client_host = client->sin_addr;

    /* eval macros and correct the byte order and alignment as needed */
    req_version = pkt_version(pkt);	/* 1 byte, version */
    req_msg_type = pkt_msg_type(pkt);	/* 1 byte, Kerberos msg type */

    /* set these to point to something safe */
    req_name_ptr = req_inst_ptr = req_realm_ptr = "";

    /* check if disabled, but we tell client */
    if (kdc_v4 == KDC_V4_DISABLE) {
	lt = klog(L_KRB_PERR,
	"KRB will not handle v4 request from %s",
		  inet_ntoa(client_host));
	/* send an error reply */
	req_name_ptr = req_inst_ptr = req_realm_ptr = "";
	kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
	return;
    }

    /* check packet version */
    if (req_version != KRB_PROT_VERSION) {
	lt = klog(L_KRB_PERR,
	"KRB prot version mismatch: KRB =%d request = %d",
		  KRB_PROT_VERSION, req_version, 0);
	/* send an error reply */
	req_name_ptr = req_inst_ptr = req_realm_ptr = "";
	kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
	return;
    }
    msg_byte_order = req_msg_type & 1;

    swap_bytes = 0;
    if (msg_byte_order != HOST_BYTE_ORDER) {
	swap_bytes++;
    }
    klog(L_KRB_PINFO,
	"Prot version: %d, Byte order: %d, Message type: %d",
	 (int) req_version, msg_byte_order, req_msg_type);

    switch (req_msg_type & ~1) {

    case AUTH_MSG_KDC_REQUEST:
	{
	    int    req_life;	/* Requested liftime */
	    unsigned int request_backdate =  0; /*How far to backdate
						  in seconds.*/
	    char   *service;	/* Service name */
	    char   *instance;	/* Service instance */
#ifdef notdef
	    int     kerno;	/* Kerberos error number */
#endif
	    n_auth_req++;
	    tk->length = 0;
	    k_flags = 0;	/* various kerberos flags */


	    /* set up and correct for byte order and alignment */
	    req_name_ptr = (char *) pkt_a_name(pkt);
	    str_length_check(req_name_ptr, ANAME_SZ);
	    req_inst_ptr = (char *) pkt_a_inst(pkt);
	    str_length_check(req_inst_ptr, INST_SZ);
	    req_realm_ptr = (char *) pkt_a_realm(pkt);
	    str_length_check(req_realm_ptr, REALM_SZ);
	    memcpy(&req_time_ws, pkt_time_ws(pkt), sizeof(req_time_ws));
	    /* time has to be diddled */
	    if (swap_bytes) {
		swap_u_long(req_time_ws);
	    }
	    ptr = (char *) pkt_time_ws(pkt) + 4;

	    req_life = (*ptr++) & 0xff;

	    service = ptr;
	    str_length_check(service, SNAME_SZ);
	    instance = ptr + strlen(service) + 1;
	    str_length_check(instance, INST_SZ);

	    rpkt = &rpkt_st;

	    klog(L_INI_REQ,
	    "Initial ticket request Host: %s User: \"%s\" \"%s\"",
	       inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0);

	    if ((i = check_princ(req_name_ptr, req_inst_ptr, 0,
				 &a_name_data, &k5key, 0, &ck5life))) {
		kerb_err_reply(client, pkt, i, "check_princ failed");
		a_name_data.key_low = a_name_data.key_high = 0;
		krb5_free_keyblock_contents(kdc_context, &k5key);
		return;
	    }
	    /* don't use k5key for client */
	    krb5_free_keyblock_contents(kdc_context, &k5key);
	    tk->length = 0;	/* init */
	    if (strcmp(service, "krbtgt"))
		klog(L_NTGT_INTK,
		    "INITIAL request from %s.%s for %s.%s", req_name_ptr,
		    req_inst_ptr, service, instance, 0);
	    /* this does all the checking */
	    if ((i = check_princ(service, instance, lifetime,
				 &s_name_data, &k5key, 1, &sk5life))) {
		kerb_err_reply(client, pkt, i, "check_princ failed");
		a_name_data.key_high = a_name_data.key_low = 0;
		s_name_data.key_high = s_name_data.key_low = 0;
		krb5_free_keyblock_contents(kdc_context, &k5key);
		return;
	    }
	    /* Bound requested lifetime with service and user */
	    v4req_end = krb_life_to_time(kerb_time.tv_sec, req_life);
	    v4req_end = min(v4req_end, kerb_time.tv_sec + ck5life);
	    v4req_end = min(v4req_end, kerb_time.tv_sec + sk5life);
	    lifetime = krb_time_to_life(kerb_time.tv_sec, v4req_end);
	    v4endtime = krb_life_to_time(kerb_time.tv_sec, lifetime);
	    /*
	     * Adjust issue time backwards if necessary, due to
	     * roundup in krb_time_to_life().
	     */
	    if (v4endtime > v4req_end)
		request_backdate = v4endtime - v4req_end;

#ifdef NOENCRYPTION
	    memset(session_key, 0, sizeof(C_Block));
#else
	    /* random session key */
	    des_new_random_key(session_key);
#endif

	    /* unseal server's key from master key */
	    memcpy( key,                &s_name_data.key_low,  4);
	    memcpy( ((krb5_ui_4 *) key) + 1, &s_name_data.key_high, 4);

	    s_name_data.key_low = s_name_data.key_high = 0;
	    kdb_encrypt_key(key, key, master_key,
			    master_key_schedule, DECRYPT);
	    /* construct and seal the ticket */
	    /* We always issue des tickets; the 3des tickets are a broken hack*/
	    krb_create_ticket(tk, k_flags, a_name_data.name,
			      a_name_data.instance, local_realm,
			      client_host.s_addr, (char *) session_key,
			      lifetime, kerb_time.tv_sec - request_backdate,
			      s_name_data.name, s_name_data.instance,
			      key);

	    krb5_free_keyblock_contents(kdc_context, &k5key);
	    memset(key, 0, sizeof(key));
	    memset(key_s, 0, sizeof(key_s));

	    /*
	     * get the user's key, unseal it from the server's key, and
	     * use it to seal the cipher 
	     */

	    /* a_name_data.key_low a_name_data.key_high */
	    memcpy( key,                &a_name_data.key_low,  4);
	    memcpy( ((krb5_ui_4 *) key) + 1, &a_name_data.key_high, 4);
	    a_name_data.key_low= a_name_data.key_high = 0;

	    /* unseal the a_name key from the master key */
	    kdb_encrypt_key(key, key, master_key, 
			    master_key_schedule, DECRYPT);

	    create_ciph(ciph, session_key, s_name_data.name,
			s_name_data.instance, local_realm, lifetime,
		  s_name_data.key_version, tk, kerb_time.tv_sec, key);

	    /* clear session key */
	    memset(session_key, 0, sizeof(session_key));

	    memset(key, 0, sizeof(key));



	    /* always send a reply packet */
	    rpkt = create_auth_reply(req_name_ptr, req_inst_ptr,
		req_realm_ptr, req_time_ws, 0, a_name_data.exp_date,
		a_name_data.key_version, ciph);
	    krb4_sendto(f, (char *) rpkt->dat, rpkt->length, 0,
		   (struct sockaddr *) client, sizeof (struct sockaddr_in));
	    memset(&a_name_data, 0, sizeof(a_name_data));
	    memset(&s_name_data, 0, sizeof(s_name_data));
	    break;
	}
    case AUTH_MSG_APPL_REQUEST:
	{
	    krb5_ui_4  time_ws;	/* Workstation time */
	    int    req_life;	/* Requested liftime */
	    char   *service;	/* Service name */
	    char   *instance;	/* Service instance */
	    int     kerno = 0;	/* Kerberos error number */
	    unsigned int request_backdate =  0; /*How far to backdate
						  in seconds.*/
	    char    tktrlm[REALM_SZ];

	    n_appl_req++;
	    tk->length = 0;
	    k_flags = 0;	/* various kerberos flags */

	    auth->mbz = 0;	/* pkt->mbz already zeroed */
	    auth->length = 4 + strlen((char *)pkt->dat + 3);
	    if (auth->length + 1 > MAX_KTXT_LEN) {
		lt = klog(L_KRB_PERR,
			  "APPL request with realm length too long from %s",
			  inet_ntoa(client_host));
		kerb_err_reply(client, pkt, RD_AP_INCON,
			       "realm length too long");
		return;
	    }

	    auth->length += (int) *(pkt->dat + auth->length) +
		(int) *(pkt->dat + auth->length + 1) + 2;
	    if (auth->length > MAX_KTXT_LEN) {
		lt = klog(L_KRB_PERR,
			  "APPL request with funky tkt or req_id length from %s",
			  inet_ntoa(client_host));
		kerb_err_reply(client, pkt, RD_AP_INCON,
			       "funky tkt or req_id length");
		return;
	    }

	    memcpy(auth->dat, pkt->dat, auth->length);

	    strncpy(tktrlm, (char *)auth->dat + 3, REALM_SZ);
	    tktrlm[REALM_SZ-1] = '\0';
	    kvno = (krb5_kvno)auth->dat[2];
	    if ((!allow_v4_crossrealm)&&strcmp(tktrlm, local_realm) != 0) {
	      lt = klog(L_ERR_UNK,
			"Cross realm ticket from %s denied by policy,", tktrlm);
	      kerb_err_reply(client, pkt,
			       KERB_ERR_PRINCIPAL_UNKNOWN, lt);
		return;
	    }
	    if (set_tgtkey(tktrlm, kvno, 0)) {
	      lt = klog(L_ERR_UNK,
			  "FAILED set_tgtkey realm %s, kvno %d. Host: %s ",
			  tktrlm, kvno, inet_ntoa(client_host));
		/* no better error code */
		kerb_err_reply(client, pkt,
			       KERB_ERR_PRINCIPAL_UNKNOWN, lt);
		return;
	    }
	    kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr,
		ad, 0);
	    if (kerno) {
		if (set_tgtkey(tktrlm, kvno, 1)) {
		    lt = klog(L_ERR_UNK,
			      "FAILED 3des set_tgtkey realm %s, kvno %d. Host: %s ",
			      tktrlm, kvno, inet_ntoa(client_host));
		    /* no better error code */
		    kerb_err_reply(client, pkt,
				   KERB_ERR_PRINCIPAL_UNKNOWN, lt);
		    return;
		}
		kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr,
				   ad, 0);
	    }

	    if (kerno) {
		klog(L_ERR_UNK, "FAILED krb_rd_req from %s: %s",
		     inet_ntoa(client_host), krb_get_err_text(kerno));
		req_name_ptr = req_inst_ptr = req_realm_ptr = "";
		kerb_err_reply(client, pkt, kerno, "krb_rd_req failed");
		return;
	    }
	    ptr = (char *) pkt->dat + auth->length;

	    memcpy(&time_ws, ptr, 4);
	    ptr += 4;

	    req_life = (*ptr++) & 0xff;

	    service = ptr;
	    str_length_check(service, SNAME_SZ);
	    instance = ptr + strlen(service) + 1;
	    str_length_check(instance, INST_SZ);

	    klog(L_APPL_REQ, "APPL Request %s.%s@%s on %s for %s.%s",
	     ad->pname, ad->pinst, ad->prealm,
	     inet_ntoa(client_host), service, instance, 0);
	    req_name_ptr = ad->pname;
	    req_inst_ptr = ad->pinst;
	    req_realm_ptr = ad->prealm;

	    if (strcmp(ad->prealm, tktrlm)) {
		kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
		     "Can't hop realms");
		return;
	    }
	    if (!strcmp(service, "changepw")) {
		kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
		     "Can't authorize password changed based on TGT");
		return;
	    }
	    kerno = check_princ(service, instance, req_life,
				&s_name_data, &k5key, 1, &sk5life);
	    if (kerno) {
		kerb_err_reply(client, pkt, kerno, "check_princ failed");
		s_name_data.key_high = s_name_data.key_low = 0;
		krb5_free_keyblock_contents(kdc_context, &k5key);
		return;
	    }
	    /* Bound requested lifetime with service and user */
	    v4endtime = krb_life_to_time((KRB4_32)ad->time_sec, ad->life);
	    v4req_end = krb_life_to_time(kerb_time.tv_sec, req_life);
	    v4req_end = min(v4endtime, v4req_end);
	    v4req_end = min(v4req_end, kerb_time.tv_sec + sk5life);

	    lifetime = krb_time_to_life(kerb_time.tv_sec, v4req_end);
	    v4endtime = krb_life_to_time(kerb_time.tv_sec, lifetime);
	    /*
	     * Adjust issue time backwards if necessary, due to
	     * roundup in krb_time_to_life().
	     */
	    if (v4endtime > v4req_end)
		request_backdate = v4endtime - v4req_end;

	    /* unseal server's key from master key */
	    memcpy(key,                &s_name_data.key_low,  4);
	    memcpy(((krb5_ui_4 *) key) + 1, &s_name_data.key_high, 4);
	    s_name_data.key_low = s_name_data.key_high = 0;
	    kdb_encrypt_key(key, key, master_key,
			    master_key_schedule, DECRYPT);
	    /* construct and seal the ticket */

#ifdef NOENCRYPTION
	    memset(session_key, 0, sizeof(C_Block));
#else
	    /* random session key */
	    des_new_random_key(session_key);
#endif

	    /* ALways issue des tickets*/
	    krb_create_ticket(tk, k_flags, ad->pname, ad->pinst,
			      ad->prealm, client_host.s_addr,
			      (char *) session_key, lifetime,
			      kerb_time.tv_sec - request_backdate,
			      s_name_data.name, s_name_data.instance,
			      key);
	    krb5_free_keyblock_contents(kdc_context, &k5key);
	    memset(key, 0, sizeof(key));
	    memset(key_s, 0, sizeof(key_s));

	    create_ciph(ciph, session_key, service, instance,
			local_realm,
			lifetime, s_name_data.key_version, tk,
			kerb_time.tv_sec, ad->session);

	    /* clear session key */
	    memset(session_key, 0, sizeof(session_key));

	    memset(ad->session, 0, sizeof(ad->session));

	    rpkt = create_auth_reply(ad->pname, ad->pinst,
				     ad->prealm, time_ws,
				     0, 0, 0, ciph);
	    krb4_sendto(f, (char *) rpkt->dat, rpkt->length, 0,
		   (struct sockaddr *) client, sizeof (struct sockaddr_in));
	    memset(&s_name_data, 0, sizeof(s_name_data));
	    break;
	}


#ifdef notdef_DIE
    case AUTH_MSG_DIE:
	{
	    lt = klog(L_DEATH_REQ,
	        "Host: %s User: \"%s\" \"%s\" Kerberos killed",
	        inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0);
	    exit(0);
	}
#endif /* notdef_DIE */

    default:
	{
	    lt = klog(L_KRB_PERR,
		"Unknown message type: %d from %s port %u",
		req_msg_type, inet_ntoa(client_host),
		ntohs(client->sin_port));
	    break;
	}
    }
}
Exemple #19
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache ccache = NULL;
    HDB *db = NULL;
    int optind = 0;

    int type = 0;

    if(getarg(args, num_args, argc, argv, &optind))
	usage(1);

    if(help_flag)
	usage(0);
    
    if(version_flag){
	print_version(NULL);
	exit(0);
    }

    ret = krb5_init_context(&context);
    if(ret)
	exit(1);

    if(local_realm)
	krb5_set_default_realm(context, local_realm);

    if(v4_realm == NULL) {
	ret = krb5_get_default_realm(context, &v4_realm);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_get_default_realm");
    }

    if(afs_cell == NULL) {
	afs_cell = strdup(v4_realm);
	if(afs_cell == NULL)
	    krb5_errx(context, 1, "out of memory");
	strlwr(afs_cell);
    }


    if(encrypt_flag && decrypt_flag)
	krb5_errx(context, 1, 
		  "only one of `--encrypt' and `--decrypt' is meaningful");

    if(source_type != NULL) {
	type = parse_source_type(source_type);
	if(type == 0)
	    krb5_errx(context, 1, "unknown source type `%s'", source_type);
    } else if(type == 0)
	type = HPROP_HEIMDAL;

    if(!to_stdout)
	get_creds(context, &ccache);
    
    if(decrypt_flag || encrypt_flag) {
	ret = hdb_read_master_key(context, mkeyfile, &mkey5);
	if(ret && ret != ENOENT)
	    krb5_err(context, 1, ret, "hdb_read_master_key");
	if(ret)
	    krb5_errx(context, 1, "No master key file found");
    }
    
#ifdef KRB4
    if (IS_TYPE_V4(type)) {
	int e;

	if (v4_realm == NULL) {
	    e = krb_get_lrealm(realm_buf, 1);
	    if(e)
		krb5_errx(context, 1, "krb_get_lrealm: %s",
			  krb_get_err_text(e));
	    v4_realm = realm_buf;
	}
    }
#endif

    switch(type) {
#ifdef KRB4
    case HPROP_KRB4_DB:
	if (database == NULL)
	    krb5_errx(context, 1, "no database specified");
	break;
#endif
    case HPROP_KASERVER:
	if (database == NULL)
	    database = DEFAULT_DATABASE;
	ka_use_null_salt = krb5_config_get_bool_default(context, NULL, FALSE, 
							"hprop", 
							"afs_uses_null_salt", 
							NULL);

	break;
    case HPROP_KRB4_DUMP:
	if (database == NULL)
	    krb5_errx(context, 1, "no dump file specified");
	
	break;
    case HPROP_MIT_DUMP:
	if (database == NULL)
	    krb5_errx(context, 1, "no dump file specified");
	break;
    case HPROP_HEIMDAL:
	ret = hdb_create (context, &db, database);
	if(ret)
	    krb5_err(context, 1, ret, "hdb_create: %s", database);
	ret = db->hdb_open(context, db, O_RDONLY, 0);
	if(ret)
	    krb5_err(context, 1, ret, "db->hdb_open");
	break;
    default:
	krb5_errx(context, 1, "unknown dump type `%d'", type);
	break;
    }

    if (to_stdout)
	dump_database (context, type, database, db);
    else
	propagate_database (context, type, database, 
			    db, ccache, optind, argc, argv);

    if(ccache != NULL)
	krb5_cc_destroy(context, ccache);
	
    if(db != NULL)
	(*db->hdb_destroy)(context, db);

    krb5_free_context(context);
    return 0;
}
Exemple #20
0
/*
 * The rcmd call itself.
 *      ahost (IN)      remote hostname
 *	addr (IN)	IP address
 *      locuser (IN)    local username
 *      remuser (IN)    remote username
 *      cmd (IN)        command to execute
 *       rank (IN)	MPI rank
 *      fd2p (IN/OUT)   if non-NULL, open stderr backchannel on this fd
 *      s (RETURN)      socket for stdout/sdin or -1 on failure
 */
static int
k4cmd(char *ahost, char *addr, char *locuser, char *remuser, char *cmd,
      int rank, int *fd2p, void **arg)
{
    KTEXT_ST ticket;            /* kerberos IV context */
    CREDENTIALS cred;
    Key_schedule schedule;
    MSG_DAT msg_data;
    struct sockaddr_in faddr;
    struct sockaddr_in laddr;

    int s, pid;
    sigset_t oldset, blockme;
    struct sockaddr_in sin, from;
    char c;
    int lport = IPPORT_RESERVED - 1;
    unsigned long krb_options = 0L;
    static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
    int status;
    int rc, rv;
    struct xpollfd xpfds[2];

    pid = getpid();

    sigemptyset(&blockme);
    sigaddset(&blockme, SIGURG);
    pthread_sigmask(SIG_BLOCK, &blockme, &oldset);
    for (;;) {
        s = privsep_rresvport(&lport);
        if (s < 0) {
            if (errno == EAGAIN)
                err("%p: %S: socket: All ports in use\n", ahost);
            else
                err("%p: %S: k4cmd: socket: %m\n", ahost);
            pthread_sigmask(SIG_SETMASK, &oldset, NULL);
            return (-1);
        }
        fcntl(s, F_SETOWN, pid);
        sin.sin_family = AF_INET;
        memcpy((caddr_t) & sin.sin_addr, addr, IP_ADDR_LEN);
        sin.sin_port = htons(KCMD_PORT);

        rv = connect(s, (struct sockaddr *) &sin, sizeof(sin));

        if (rv >= 0)
            break;
        (void) close(s);
        if (errno == EADDRINUSE) {
            lport--;
            continue;
        }
        if (errno == EINTR)
            err("%p: %S: connect timed out\n", ahost);
        else
            err("%p: %S: %m\n", ahost);
        pthread_sigmask(SIG_SETMASK, &oldset, NULL);
        return (-1);
    }
    if (fd2p == 0) {
        write(s, "", 1);
        lport = 0;
    } else {
        char num[8];
        int s2, s3;
        socklen_t len = sizeof(from);

        s2 = privsep_rresvport(&lport);
        if (s2 < 0) {
            goto bad;
        }
        listen(s2, 1);
        (void) snprintf(num, sizeof(num), "%d", lport);
        if (write(s, num, strlen(num) + 1) != strlen(num) + 1) {
            err("%p: %S: write: setting up stderr: %m\n", ahost);
            (void) close(s2);
            goto bad;
        }
        errno = 0;
        xpfds[0].fd = s;
        xpfds[1].fd = s2;
        xpfds[0].events = xpfds[1].events = XPOLLREAD;
        if (((rv = xpoll(xpfds, 2, -1)) < 0) || rv != 1 || (xpfds[0].revents > 0)) {
          if (errno != 0)
            err("%p: %S: k4cmd: xpoll (setting up stderr): %m\n", ahost);
          else
            err("%p: %S: k4cmd: xpoll: protocol failure in circuit setup\n", ahost);
          (void) close(s2);
          goto bad;
        }
        s3 = accept(s2, (struct sockaddr *) &from, &len);
        (void) close(s2);
        if (s3 < 0) {
            err("%p: %S: accept: %m\n", ahost);
            lport = 0;
            goto bad;
        }
        *fd2p = s3;
        from.sin_port = ntohs((u_short) from.sin_port);
    }

    /*
     * Kerberos-authenticated service.  Don't have to send locuser, since
     * its already in the ticket, and we'll extract it on the other side. 
     */
    /*krb_options |= KOPT_DONT_CANON; */
    pthread_mutex_lock(&mylock);
    status = krb_sendauth(krb_options, s, &ticket, "rcmd", ahost,
                          NULL, (unsigned long) pid, &msg_data,
                          &cred, schedule, &laddr, &faddr, "KCMDV0.1");

    if (status != KSUCCESS) {
        /*
         * this part involves some very intimate knowledge of a
         * particular sendauth implementation to pry out the old
         * bits. This only catches the case of total failure -- but
         * that's the one where we get useful data from the remote
         * end. If we even get an authenticator back, then the
         * problem gets diagnosed locally anyhow. 
         */
        extern KRB_INT32 __krb_sendauth_hidden_tkt_len;
        char *old_data = (char *) &__krb_sendauth_hidden_tkt_len;
        char tmpbuf[LINEBUFSIZE];
        char *p = tmpbuf;

        if ((status == KFAILURE) && (*old_data == 1)) {
            strncpy(tmpbuf, old_data + 1, 3);
            tmpbuf[3] = '\0';
            err("%p: %S: %s", ahost, tmpbuf);
            *old_data = (-1);
        }
        if ((status == KFAILURE) && (*old_data == (char) -1)) {
            while (read(s, &c, 1) == 1) {
                /*(void) write(2, &c, 1); */
                *p++ = c;
                if (c == '\n')
                    break;
            }
            *p++ = '\0';
            err("%p: %S: %s", ahost, tmpbuf);
            status = -1;
        }
        switch (status) {
        case KDC_PR_UNKNOWN:
            err("%p: %S: not registered for kerberos\n", ahost);
            break;
        case NO_TKT_FIL:
            err("%p: %S: no tickets file found\n", ahost);
            break;
        default:
            err("%p: %S: k4cmd failed: %s\n", ahost,
                (status == -1) ? "k4cmd protocol failure" :
                krb_get_err_text(status));
        }
        pthread_mutex_unlock(&mylock);
        goto bad2;
    }
    pthread_mutex_unlock(&mylock);
    (void) write(s, remuser, strlen(remuser) + 1);
    (void) write(s, cmd, strlen(cmd) + 1);

    if ((rc = read(s, &c, 1)) != 1) {
        if (rc == -1) {
            err("%p: %S: read: %m\n", ahost);
        } else {
            err("%p: %S: k4cmd: bad connection with remote host\n", ahost);
        }
        goto bad2;
    }
    if (c != 0) {
        /* retrieve error string from remote server */
        char tmpbuf[LINEBUFSIZE];
        char *p = tmpbuf;

        while (read(s, &c, 1) == 1) {
            *p++ = c;
            if (c == '\n')
                break;
        }
        if (c != '\n')
            *p++ = '\n';
        *p++ = '\0';
        err("%S: %s", ahost, tmpbuf);
        goto bad2;
    }
    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
    return (s);
  bad2:
    if (lport)
        (void) close(*fd2p);
  bad:
    (void) close(s);
    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
    return (-1);
}
Exemple #21
0
/*
 * Function: Process WM_COMMAND messages
 */
static void
kwin_command(HWND hwnd, int cid, HWND hwndCtl, UINT codeNotify)
{
  char                      name[ANAME_SZ];
  char                      realm[REALM_SZ];
  char                      password[MAX_KPW_LEN];
  HCURSOR                   hcursor;
  BOOL                      blogin;
  HMENU                     hmenu;
  char                      menuitem[MAX_K_NAME_SZ + 3];
  char                      copyright[128];
  int                       id;
#ifdef KRB4
  char                      instance[INST_SZ];
  int                       lifetime;
  int                       krc;
#endif
#ifdef KRB5
  long                      lifetime;
  krb5_error_code           code;
  krb5_principal            principal;
  krb5_creds                creds;
  krb5_get_init_creds_opt   opts;
  gic_data                  gd;
#endif

#ifdef KRB4
  EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), krb_get_num_cred() > 0);
#endif

#ifdef KRB5
  EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), k5_get_num_cred(1) > 0);
#endif

  GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
  trim(name);
  blogin = strlen(name) > 0;

  if (blogin) {
    GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm));
    trim(realm);
    blogin = strlen(realm) > 0;
  }

  if (blogin) {
    GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password));
    blogin = strlen(password) > 0;
  }

  EnableWindow(GetDlgItem(hwnd, IDD_LOGIN), blogin);
  id = (blogin) ? IDD_LOGIN : IDD_PASSWORD_CR2;
  SendMessage(hwnd, DM_SETDEFID, id, 0);

  if (codeNotify != BN_CLICKED && codeNotify != 0 && codeNotify != 1)
    return; /* FALSE */

  /*
   * Check to see if this item is in a list of the ``recent hosts'' sort
   * of list, under the FILE menu.
   */
  if (cid >= IDM_FIRST_LOGIN && cid < IDM_FIRST_LOGIN + FILE_MENU_MAX_LOGINS) {
    hmenu = GetMenu(hwnd);
    assert(hmenu != NULL);

    hmenu = GetSubMenu(hmenu, 0);
    assert(hmenu != NULL);

    if (!GetMenuString(hmenu, cid, menuitem, sizeof(menuitem), MF_BYCOMMAND))
      return; /* TRUE */

    if (menuitem[0])
      kwin_init_name(hwnd, &menuitem[3]);

    return; /* TRUE */
  }

  switch (cid) {
  case IDM_EXIT:
    if (isblocking)
      WSACancelBlockingCall();
    WinHelp(hwnd, KERBEROS_HLP, HELP_QUIT, 0);
    PostQuitMessage(0);

    return; /* TRUE */

  case IDD_PASSWORD_CR2:                      /* Make CR == TAB */
    id = GetDlgCtrlID(GetFocus());
    assert(id != 0);

    if (id == IDD_MAX_EDIT)
      PostMessage(hwnd, WM_NEXTDLGCTL,
		  (WPARAM)GetDlgItem(hwnd, IDD_MIN_EDIT), MAKELONG(1, 0));
    else
      PostMessage(hwnd, WM_NEXTDLGCTL, 0, 0);

    return; /* TRUE */

  case IDD_LOGIN:
    if (isblocking)
      return; /* TRUE */

    GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
    trim(name);
    GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm));
    trim(realm);
    GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password));
    SetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, "");  /* nuke the password */
    trim(password);

#ifdef KRB4
    GetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance, sizeof(instance));
    trim(instance);
#endif

    hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
    lifetime = cns_res.lifetime;
    start_blocking_hook(BLOCK_MAX_SEC);

#ifdef KRB4
    lifetime = (lifetime + 4) / 5;
    krc = krb_get_pw_in_tkt(name, instance, realm, "krbtgt", realm,
			    lifetime, password);
#endif

#ifdef KRB5
    principal = NULL;

    /*
     * convert the name + realm into a krb5 principal string and parse it into a principal
     */
    sprintf(menuitem, "%s@%s", name, realm);
    code = krb5_parse_name(k5_context, menuitem, &principal);
    if (code)
      goto errorpoint;

    /*
     * set the various ticket options.  First, initialize the structure, then set the ticket
     * to be forwardable if desired, and set the lifetime.
     */
    krb5_get_init_creds_opt_init(&opts);
    krb5_get_init_creds_opt_set_forwardable(&opts, forwardable);
    krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime * 60);
    if (noaddresses) {
		krb5_get_init_creds_opt_set_address_list(&opts, NULL);
 	}

    /*
     * get the initial creds using the password and the options we set above
     */
    gd.hinstance = hinstance;
    gd.hwnd = hwnd;
    gd.id = ID_VARDLG;
    code = krb5_get_init_creds_password(k5_context, &creds, principal, password,
					gic_prompter, &gd, 0, NULL, &opts);
    if (code)
      goto errorpoint;

    /*
     * initialize the credential cache
     */
    code = krb5_cc_initialize(k5_context, k5_ccache, principal);
    if (code)
      goto errorpoint;

    /*
     * insert the principal into the cache
     */
    code = krb5_cc_store_cred(k5_context, k5_ccache, &creds);

  errorpoint:

    if (principal)
      krb5_free_principal(k5_context, principal);

    end_blocking_hook();
    SetCursor(hcursor);
    kwin_set_default_focus(hwnd);

    if (code) {
      if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
	MessageBox(hwnd, "Password incorrect", NULL,
		   MB_OK | MB_ICONEXCLAMATION);
      else
	com_err(NULL, code, "while logging in");
    }
#endif /* KRB5 */

#ifdef KRB4
    if (krc != KSUCCESS) {
      MessageBox(hwnd, krb_get_err_text(krc),	"",
		 MB_OK | MB_ICONEXCLAMATION);

      return; /* TRUE */
    }
#endif

    kwin_save_name(hwnd);
    alerted = FALSE;

    switch (action) {
    case LOGIN_AND_EXIT:
      SendMessage(hwnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_EXIT, 0, 0));
      break;

    case LOGIN_AND_MINIMIZE:
      ShowWindow(hwnd, SW_MINIMIZE);
      break;
    }

    return; /* TRUE */

  case IDD_TICKET_DELETE:
    if (isblocking)
      return; /* TRUE */

#ifdef KRB4
    krc = dest_tkt();
    if (krc != KSUCCESS)
      MessageBox(hwnd, krb_get_err_text(krc),	"",
		 MB_OK | MB_ICONEXCLAMATION);
#endif

#ifdef KRB5
    code = k5_dest_tkt();
#endif

    kwin_set_default_focus(hwnd);
    alerted = FALSE;

    return; /* TRUE */

  case IDD_CHANGE_PASSWORD:
    if (isblocking)
      return; /* TRUE */
    password_dialog(hwnd);
    kwin_set_default_focus(hwnd);

    return; /* TRUE */

  case IDM_OPTIONS:
    if (isblocking)
      return; /* TRUE */
    opts_dialog(hwnd);

    return; /* TRUE */

  case IDM_HELP_INDEX:
    WinHelp(hwnd, KERBEROS_HLP, HELP_INDEX, 0);

    return; /* TRUE */

  case IDM_ABOUT:
    ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST));
    if (isblocking)
      return; /* TRUE */

#ifdef KRB4
    strcpy(copyright, "        Kerberos 4 for Windows ");
#endif
#ifdef KRB5
    strcpy(copyright, "        Kerberos V5 for Windows ");
#endif
#ifdef _WIN32
    strncat(copyright, "32-bit\n", sizeof(copyright) - 1 - strlen(copyright));
#else
    strncat(copyright, "16-bit\n", sizeof(copyright) - 1 - strlen(copyright));
#endif
    strncat(copyright, "\n                Version 1.12\n\n",
            sizeof(copyright) - 1 - strlen(copyright));
#ifdef ORGANIZATION
    strncat(copyright, "          For information, contact:\n",
	    sizeof(copyright) - 1 - strlen(copyright));
    strncat(copyright, ORGANIZATION, sizeof(copyright) - 1 - strlen(copyright));
#endif
    MessageBox(hwnd, copyright, KWIN_DIALOG_NAME, MB_OK);

    return; /* TRUE */
  }

  return; /* FALSE */
}
Exemple #22
0
static int
krb4_auth(void *app_data, char *host)
{
    int ret;
    char *p;
    int len;
    KTEXT_ST adat;
    MSG_DAT msg_data;
    int checksum;
    uint32_t cs;
    struct krb4_data *d = app_data;
    struct sockaddr_in *localaddr  = (struct sockaddr_in *)LOCAL_ADDR;
    struct sockaddr_in *remoteaddr = (struct sockaddr_in *)REMOTE_ADDR;

    checksum = getpid();
    ret = mk_auth(d, &adat, "ftp", host, checksum);
    if(ret == KDC_PR_UNKNOWN)
	ret = mk_auth(d, &adat, "rcmd", host, checksum);
    if(ret){
	printf("%s\n", krb_get_err_text(ret));
	return AUTH_CONTINUE;
    }

#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
    if (krb_get_config_bool("nat_in_use")) {
      struct in_addr natAddr;

      if (krb_get_our_ip_for_realm(krb_realmofhost(host),
				   &natAddr) != KSUCCESS
	  && krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
	printf("Can't get address for realm %s\n",
	       krb_realmofhost(host));
      else {
	if (natAddr.s_addr != localaddr->sin_addr.s_addr) {
	  printf("Using NAT IP address (%s) for kerberos 4\n",
		 inet_ntoa(natAddr));
	  localaddr->sin_addr = natAddr;
	  
	  /*
	   * This not the best place to do this, but it
	   * is here we know that (probably) NAT is in
	   * use!
	   */

	  passivemode = 1;
	  printf("Setting: Passive mode on.\n");
	}
      }
    }
#endif

    printf("Local address is %s\n", inet_ntoa(localaddr->sin_addr));
    printf("Remote address is %s\n", inet_ntoa(remoteaddr->sin_addr));

   if(base64_encode(adat.dat, adat.length, &p) < 0) {
	printf("Out of memory base64-encoding.\n");
	return AUTH_CONTINUE;
    }
    ret = command("ADAT %s", p);
    free(p);

    if(ret != COMPLETE){
	printf("Server didn't accept auth data.\n");
	return AUTH_ERROR;
    }

    p = strstr(reply_string, "ADAT=");
    if(!p){
	printf("Remote host didn't send adat reply.\n");
	return AUTH_ERROR;
    }
    p += 5;
    len = base64_decode(p, adat.dat);
    if(len < 0){
	printf("Failed to decode base64 from server.\n");
	return AUTH_ERROR;
    }
    adat.length = len;
    ret = krb_rd_safe(adat.dat, adat.length, &d->key, 
		      (struct sockaddr_in *)hisctladdr, 
		      (struct sockaddr_in *)myctladdr, &msg_data);
    if(ret){
	printf("Error reading reply from server: %s.\n", 
	       krb_get_err_text(ret));
	return AUTH_ERROR;
    }
    krb_get_int(msg_data.app_data, &cs, 4, 0);
    if(cs - checksum != 1){
	printf("Bad checksum returned from server.\n");
	return AUTH_ERROR;
    }
    return AUTH_OK;
}
Exemple #23
0
void
doit(struct sockaddr *fromp)
{
	extern char *__rcmd_errstr;	/* syslog hook from libc/net/rcmd.c. */
	struct addrinfo hints, *res, *res0;
	int gaierror;
	struct passwd *pwd;
	u_short port;
	in_port_t *portp;
	struct pollfd pfd[4];
	int cc, nfd, pv[2], s = 0, one = 1;
	pid_t pid;
	char *hostname, *errorstr, *errorhost = (char *) NULL;
	char *cp, sig, buf[BUFSIZ];
	char cmdbuf[NCARGS+1], locuser[_PW_NAME_LEN+1], remuser[_PW_NAME_LEN+1];
	char remotehost[2 * MAXHOSTNAMELEN + 1];
	char hostnamebuf[2 * MAXHOSTNAMELEN + 1];
	char naddr[NI_MAXHOST];
	char saddr[NI_MAXHOST];
	char raddr[NI_MAXHOST];
	char pbuf[NI_MAXSERV];
	auth_session_t *as;
	const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;

#ifdef	KERBEROS
	AUTH_DAT	*kdata = (AUTH_DAT *) NULL;
	KTEXT		ticket = (KTEXT) NULL;
	char		instance[INST_SZ], version[VERSION_SIZE];
	struct		sockaddr_storage fromaddr;
	int		rc;
	long		authopts;
#ifdef CRYPT
	int		pv1[2], pv2[2];
#endif

	if (sizeof(fromaddr) < fromp->sa_len) {
		syslog(LOG_ERR, "malformed \"from\" address (af %d)",
		    fromp->sa_family);
		exit(1);
	}
	memcpy(&fromaddr, fromp, fromp->sa_len);
#endif

	(void) signal(SIGINT, SIG_DFL);
	(void) signal(SIGQUIT, SIG_DFL);
	(void) signal(SIGTERM, SIG_DFL);
#ifdef DEBUG
	{ int t = open(_PATH_TTY, 2);
	  if (t >= 0) {
		ioctl(t, TIOCNOTTY, (char *)0);
		(void) close(t);
	  }
	}
#endif
	switch (fromp->sa_family) {
	case AF_INET:
		portp = &((struct sockaddr_in *)fromp)->sin_port;
		break;
	case AF_INET6:
		portp = &((struct sockaddr_in6 *)fromp)->sin6_port;
		break;
	default:
		syslog(LOG_ERR, "malformed \"from\" address (af %d)",
		    fromp->sa_family);
		exit(1);
	}
	if (getnameinfo(fromp, fromp->sa_len, naddr, sizeof(naddr),
	    pbuf, sizeof(pbuf), niflags) != 0) {
		syslog(LOG_ERR, "malformed \"from\" address (af %d)",
		    fromp->sa_family);
		exit(1);
	}

#ifdef IP_OPTIONS
	if (fromp->sa_family == AF_INET) {
		struct ipoption opts;
		socklen_t optsize = sizeof(opts);
		int ipproto, i;
		struct protoent *ip;

		if ((ip = getprotobyname("ip")) != NULL)
			ipproto = ip->p_proto;
		else
			ipproto = IPPROTO_IP;
		if (!getsockopt(STDIN_FILENO, ipproto, IP_OPTIONS,
		    (char *)&opts, &optsize) && optsize != 0) {
			for (i = 0; (void *)&opts.ipopt_list[i] - (void *)&opts <
			    optsize; ) {
				u_char c = (u_char)opts.ipopt_list[i];
				if (c == IPOPT_LSRR || c == IPOPT_SSRR)
					exit(1);
				if (c == IPOPT_EOL)
					break;
				i += (c == IPOPT_NOP) ? 1 :
				    (u_char)opts.ipopt_list[i+1];
			}
		}
	}
#endif

#ifdef	KERBEROS
	if (!use_kerberos)
#endif
		if (ntohs(*portp) >= IPPORT_RESERVED ||
		    ntohs(*portp) < IPPORT_RESERVED/2) {
			syslog(LOG_NOTICE|LOG_AUTH,
			    "Connection from %s on illegal port %u",
			    naddr, ntohs(*portp));
			exit(1);
		}

	(void) alarm(60);
	port = 0;
	for (;;) {
		char c;
		if ((cc = read(STDIN_FILENO, &c, 1)) != 1) {
			if (cc < 0)
				syslog(LOG_NOTICE, "read: %m");
			shutdown(STDIN_FILENO, SHUT_RDWR);
			exit(1);
		}
		if (c == 0)
			break;
		port = port * 10 + c - '0';
	}

	(void) alarm(0);
	if (port != 0) {
		int lport;
#ifdef	KERBEROS
		if (!use_kerberos)
#endif
			if (port >= IPPORT_RESERVED ||
			    port < IPPORT_RESERVED/2) {
				syslog(LOG_ERR, "2nd port not reserved");
				exit(1);
			}
		*portp = htons(port);
		lport = IPPORT_RESERVED - 1;
		s = rresvport_af(&lport, fromp->sa_family);
		if (s < 0) {
			syslog(LOG_ERR, "can't get stderr port: %m");
			exit(1);
		}
		if (connect(s, (struct sockaddr *)fromp, fromp->sa_len) < 0) {
			syslog(LOG_INFO, "connect second port %d: %m", port);
			exit(1);
		}
	}

#ifdef	KERBEROS
	if (vacuous) {
		error("rshd: remote host requires Kerberos authentication\n");
		exit(1);
	}
#endif

#ifdef notdef
	/* from inetd, socket is already on 0, 1, 2 */
	dup2(f, 0);
	dup2(f, 1);
	dup2(f, 2);
#endif
	errorstr = NULL;
	if (getnameinfo(fromp, fromp->sa_len, saddr, sizeof(saddr),
			NULL, 0, NI_NAMEREQD)== 0) {
		/*
		 * If name returned by getnameinfo is in our domain,
		 * attempt to verify that we haven't been fooled by someone
		 * in a remote net; look up the name and check that this
		 * address corresponds to the name.
		 */
		hostname = saddr;
		res0 = NULL;
#ifdef	KERBEROS
		if (!use_kerberos)
#endif
		if (check_all || local_domain(saddr)) {
			strlcpy(remotehost, saddr, sizeof(remotehost));
			errorhost = remotehost;
			memset(&hints, 0, sizeof(hints));
			hints.ai_family = fromp->sa_family;
			hints.ai_socktype = SOCK_STREAM;
			hints.ai_flags = AI_CANONNAME;
			gaierror = getaddrinfo(remotehost, pbuf, &hints, &res0);
			if (gaierror) {
				syslog(LOG_INFO,
				    "Couldn't look up address for %s: %s",
				    remotehost, gai_strerror(gaierror));
				errorstr =
				"Couldn't look up address for your host (%s)\n";
				hostname = naddr;
			} else {
				for (res = res0; res; res = res->ai_next) {
					if (res->ai_family != fromp->sa_family)
						continue;
					if (res->ai_addrlen != fromp->sa_len)
						continue;
					if (getnameinfo(res->ai_addr,
						res->ai_addrlen,
						raddr, sizeof(raddr), NULL, 0,
						niflags) == 0
					 && strcmp(naddr, raddr) == 0) {
						hostname = res->ai_canonname
							? res->ai_canonname
							: saddr;
						break;
					}
				}
				if (res == NULL) {
					syslog(LOG_NOTICE,
					  "Host addr %s not listed for host %s",
					    naddr, res0->ai_canonname
							? res0->ai_canonname
							: saddr);
					errorstr =
					    "Host address mismatch for %s\n";
					hostname = naddr;
				}
			}
		}
		strlcpy(hostnamebuf, hostname, sizeof(hostnamebuf));
		hostname = hostnamebuf;
		if (res0)
			freeaddrinfo(res0);
	} else
		strlcpy(hostnamebuf, naddr, sizeof(hostnamebuf));
		errorhost = hostname = hostnamebuf;

#ifdef	KERBEROS
	if (use_kerberos) {
		kdata = (AUTH_DAT *) authbuf;
		ticket = (KTEXT) tickbuf;
		authopts = 0L;
		strlcpy(instance, "*", sizeof instance);
		version[VERSION_SIZE - 1] = '\0';
#ifdef CRYPT
		if (doencrypt) {
			struct sockaddr_in local_addr;

			rc = sizeof(local_addr);
			if (getsockname(STDIN_FILENO,
			    (struct sockaddr *)&local_addr, &rc) < 0) {
				syslog(LOG_ERR, "getsockname: %m");
				error("rshd: getsockname: %m");
				exit(1);
			}
			authopts = KOPT_DO_MUTUAL;
			rc = krb_recvauth(authopts, 0, ticket,
			    "rcmd", instance, (struct sockaddr_in *)&fromaddr,
			    &local_addr, kdata, "", schedule, version);
			desrw_set_key(&kdata->session, &schedule);
		} else
#endif
			rc = krb_recvauth(authopts, 0, ticket, "rcmd",
			    instance, (struct sockaddr_in *)&fromaddr,
			    NULL, kdata, "", NULL, version);
		if (rc != KSUCCESS) {
			error("Kerberos authentication failure: %s\n",
				  krb_get_err_text(rc));
			exit(1);
		}
	} else
#endif

	getstr(remuser, sizeof(remuser), "remuser");
	getstr(locuser, sizeof(locuser), "locuser");
	getstr(cmdbuf, sizeof(cmdbuf), "command");
	pwd = getpwnam(locuser);
	if (pwd == NULL) {
		syslog(LOG_INFO|LOG_AUTH,
		    "%s@%s as %s: unknown login. cmd='%.80s'",
		    remuser, hostname, locuser, cmdbuf);
		if (errorstr == NULL)
			errorstr = "Permission denied.\n";
		goto fail;
	}
	lc = login_getclass(pwd->pw_class);
	if (lc == NULL) {
		syslog(LOG_INFO|LOG_AUTH,
		    "%s@%s as %s: unknown class. cmd='%.80s'",
		    remuser, hostname, locuser, cmdbuf);
		if (errorstr == NULL)
			errorstr = "Login incorrect.\n";
		goto fail;
	}
	as = auth_open();
	if (as == NULL || auth_setpwd(as, pwd) != 0) {
		syslog(LOG_INFO|LOG_AUTH,
		    "%s@%s as %s: unable to allocate memory. cmd='%.80s'",
		    remuser, hostname, locuser, cmdbuf);
		if (errorstr == NULL)
			errorstr = "Cannot allocate memory.\n";
		goto fail;
	}

	setegid(pwd->pw_gid);
	seteuid(pwd->pw_uid);
	if (chdir(pwd->pw_dir) < 0) {
		(void) chdir("/");
#ifdef notdef
		syslog(LOG_INFO|LOG_AUTH,
		    "%s@%s as %s: no home directory. cmd='%.80s'",
		    remuser, hostname, locuser, cmdbuf);
		error("No remote directory.\n");
		exit(1);
#endif
	}
	seteuid(0);
	setegid(0);	/* XXX use a saved gid instead? */

#ifdef	KERBEROS
	if (use_kerberos) {
		if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') {
			if (kuserok(kdata, locuser) != 0) {
				syslog(LOG_INFO|LOG_AUTH,
				    "Kerberos rsh denied to %s.%s@%s",
				    kdata->pname, kdata->pinst, kdata->prealm);
				error("Permission denied.\n");
				exit(1);
			}
		}
	} else
#endif
	if (errorstr ||
	    (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
	    iruserok_sa(fromp, fromp->sa_len, pwd->pw_uid == 0,
	    remuser, locuser) < 0)) {
		if (__rcmd_errstr)
			syslog(LOG_INFO|LOG_AUTH,
			    "%s@%s as %s: permission denied (%s). cmd='%.80s'",
			    remuser, hostname, locuser, __rcmd_errstr,
			    cmdbuf);
		else
			syslog(LOG_INFO|LOG_AUTH,
			    "%s@%s as %s: permission denied. cmd='%.80s'",
			    remuser, hostname, locuser, cmdbuf);
fail:
		if (errorstr == NULL)
			errorstr = "Permission denied.\n";
		error(errorstr, errorhost);
		exit(1);
	}

	if (pwd->pw_uid)
		auth_checknologin(lc);

	(void) write(STDERR_FILENO, "\0", 1);
	sent_null = 1;

	if (port) {
		if (pipe(pv) < 0) {
			error("Can't make pipe.\n");
			exit(1);
		}
#ifdef CRYPT
#ifdef KERBEROS
		if (doencrypt) {
			if (pipe(pv1) < 0) {
				error("Can't make 2nd pipe.\n");
				exit(1);
			}
			if (pipe(pv2) < 0) {
				error("Can't make 3rd pipe.\n");
				exit(1);
			}
		}
#endif
#endif
		pid = fork();
		if (pid == -1)  {
			error("Can't fork; try again.\n");
			exit(1);
		}
		if (pid) {
#ifdef CRYPT
#ifdef KERBEROS
			if (doencrypt) {
				static char msg[] = SECURE_MESSAGE;
				(void) close(pv1[1]);
				(void) close(pv2[1]);
				des_write(s, msg, sizeof(msg) - 1);

			} else
#endif
#endif
			{
				(void) close(STDIN_FILENO);
				(void) close(STDOUT_FILENO);
			}
			(void) close(STDERR_FILENO);
			(void) close(pv[1]);

			pfd[P_SOCKREAD].fd = s;
			pfd[P_SOCKREAD].events = POLLIN;
			pfd[P_PIPEREAD].fd = pv[0];
			pfd[P_PIPEREAD].events = POLLIN;
			nfd = 2;
#ifdef CRYPT
#ifdef KERBEROS
			if (doencrypt) {
				pfd[P_CRYPTREAD].fd = pv1[0];
				pfd[P_CRYPTREAD].events = POLLIN;
				pfd[P_CRYPTWRITE].fd = pv2[0];
				pfd[P_CRYPTWRITE].events = POLLOUT;
				nfd += 2;
			} else
#endif
#endif
				ioctl(pv[0], FIONBIO, (char *)&one);

			/* should set s nbio! */
			do {
				if (poll(pfd, nfd, INFTIM) < 0)
					break;
				if (pfd[P_SOCKREAD].revents & POLLIN) {
					int	ret;
#ifdef CRYPT
#ifdef KERBEROS
					if (doencrypt)
						ret = des_read(s, &sig, 1);
					else
#endif
#endif
						ret = read(s, &sig, 1);
					if (ret <= 0)
						pfd[P_SOCKREAD].revents = 0;
					else
						killpg(pid, sig);
				}
				if (pfd[P_PIPEREAD].revents & POLLIN) {
					errno = 0;
					cc = read(pv[0], buf, sizeof(buf));
					if (cc <= 0) {
						shutdown(s, SHUT_RDWR);
						pfd[P_PIPEREAD].revents = 0;
					} else {

#ifdef CRYPT
#ifdef KERBEROS
						if (doencrypt)
							(void)
							  des_write(s, buf, cc);
						else
#endif
#endif
							(void)
							  write(s, buf, cc);
					}
				}
#ifdef CRYPT
#ifdef KERBEROS
				if (doencrypt &&
				    (pfd[P_CRYPTREAD].revents & POLLIN)) {
					errno = 0;
					cc = read(pv1[0], buf, sizeof(buf));
					if (cc <= 0) {
						shutdown(pv1[0], SHUT_RDWR);
						pfd[P_CRYPTREAD].revents = 0;
					} else
						(void) des_write(STDOUT_FILENO,
						    buf, cc);
				}

				if (doencrypt &&
				    (pfd[P_CRYPTWRITE].revents & POLLIN)) {
					errno = 0;
					cc = des_read(STDIN_FILENO,
					    buf, sizeof(buf));
					if (cc <= 0) {
						shutdown(pv2[0], SHUT_RDWR);
						pfd[P_CRYPTWRITE].revents = 0;
					} else
						(void) write(pv2[0], buf, cc);
				}
#endif
#endif

			} while ((pfd[P_SOCKREAD].revents & POLLIN) ||
#ifdef CRYPT
#ifdef KERBEROS
			    (doencrypt && (pfd[P_CRYPTREAD].revents & POLLIN)) ||
#endif
#endif
			    (pfd[P_PIPEREAD].revents & POLLIN));
			exit(0);
		}
		setsid();
		(void) close(s);
		(void) close(pv[0]);
#ifdef CRYPT
#ifdef KERBEROS
		if (doencrypt) {
			close(pv1[0]); close(pv2[0]);
			dup2(pv1[1], 1);
			dup2(pv2[1], 0);
			close(pv1[1]);
			close(pv2[1]);
		}
#endif
#endif
		dup2(pv[1], 2);
		close(pv[1]);
	} else
		setsid();
	if (*pwd->pw_shell == '\0')
		pwd->pw_shell = _PATH_BSHELL;

	environ = envinit;
	if (setenv("HOME", pwd->pw_dir, 1) == -1 ||
	    setenv("SHELL", pwd->pw_shell, 1) == -1 ||
	    setenv("USER", pwd->pw_name, 1) == -1 ||
	    setenv("LOGNAME", pwd->pw_name, 1) == -1)
		errx(1, "cannot setup environment");

	if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETALL))
		errx(1, "cannot set user context");
	if (auth_approval(as, lc, pwd->pw_name, "rsh") <= 0)
		errx(1, "approval failure");
	auth_close(as);
	login_close(lc);

	cp = strrchr(pwd->pw_shell, '/');
	if (cp)
		cp++;
	else
		cp = pwd->pw_shell;
	endpwent();
	if (log_success || pwd->pw_uid == 0) {
#ifdef	KERBEROS
		if (use_kerberos)
		    syslog(LOG_INFO|LOG_AUTH,
			"Kerberos shell from %s.%s@%s on %s as %s, cmd='%.80s'",
			kdata->pname, kdata->pinst, kdata->prealm,
			hostname, locuser, cmdbuf);
		else
#endif
		    syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'",
			remuser, hostname, locuser, cmdbuf);
	}
	execl(pwd->pw_shell, cp, "-c", cmdbuf, (char *)NULL);
	perror(pwd->pw_shell);
	exit(1);
}
Exemple #24
0
static int
kerberos4_send(char *name, Authenticator *ap)
{
    KTEXT_ST auth;
    char instance[INST_SZ];
    char *realm;
    CREDENTIALS cred;
    int r;

    printf("[ Trying %s ... ]\r\n", name);
    if (!UserNameRequested) {
	if (auth_debug_mode) {
	    printf("Kerberos V4: no user name supplied\r\n");
	}
	return(0);
    }

    memset(instance, 0, sizeof(instance));

    if ((realm = krb_get_phost(RemoteHostName)))
	strncpy(instance, realm, sizeof(instance));

    instance[sizeof(instance)-1] = '\0';

    realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName);

    if (!realm) {
	printf("Kerberos V4: no realm for %s\r\n", RemoteHostName);
	return(0);
    }
    r = krb_mk_req(&auth, KRB_SERVICE_NAME, instance, realm, 0L);
    if (r) {
	printf("mk_req failed: %s\r\n", krb_get_err_text(r));
	return(0);
    }
    r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred);
    if (r) {
	printf("get_cred failed: %s\r\n", krb_get_err_text(r));
	return(0);
    }
    if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
	if (auth_debug_mode)
	    printf("Not enough room for user name\r\n");
	return(0);
    }
    if (auth_debug_mode)
	printf("Sent %d bytes of authentication data\r\n", auth.length);
    if (!Data(ap, KRB_AUTH, (void *)auth.dat, auth.length)) {
	if (auth_debug_mode)
	    printf("Not enough room for authentication data\r\n");
	return(0);
    }
#ifdef ENCRYPTION
    /* create challenge */
    if ((ap->way & AUTH_HOW_MASK)==AUTH_HOW_MUTUAL) {
	int i;

	des_key_sched(&cred.session, sched);
	des_init_random_number_generator(&cred.session);
	des_new_random_key(&session_key);
	des_ecb_encrypt(&session_key, &session_key, sched, 0);
	des_ecb_encrypt(&session_key, &challenge, sched, 0);

	/*
	  old code
	  Some CERT Advisory thinks this is a bad thing...
	    
	  des_init_random_number_generator(&cred.session);
	  des_new_random_key(&challenge);
	  des_ecb_encrypt(&challenge, &session_key, sched, 1);
	  */
	  
	/*
	 * Increment the challenge by 1, and encrypt it for
	 * later comparison.
	 */
	for (i = 7; i >= 0; --i) 
	    if(++challenge[i] != 0) /* No carry! */
		break;
	des_ecb_encrypt(&challenge, &challenge, sched, 1);
    }

#endif

    if (auth_debug_mode) {
	printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
	printd(auth.dat, auth.length);
	printf("\r\n");
	printf("Sent Kerberos V4 credentials to server\r\n");
    }
    return(1);
}
Exemple #25
0
/* This function has not been changed to deal with NO_SOCKET_TO_FD
   (i.e., systems on which sockets cannot be converted to file
   descriptors).  The first person to try building a kerberos client
   on such a system (OS/2, Windows 95, and maybe others) will have to
   take care of this.  */
void
start_kerberos4_server (cvsroot_t *root, struct buffer **to_server_p,
                        struct buffer **from_server_p)
{
    int s;
    int port;
    struct hostent *hp;
    struct sockaddr_in sin;
    char *hname;

    s = socket (AF_INET, SOCK_STREAM, 0);
    if (s < 0)
	error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO));

    port = get_cvs_port_number (root);

    hp = init_sockaddr (&sin, root->hostname, port);

    hname = xstrdup (hp->h_name);
  
    TRACE (TRACE_FUNCTION, "Connecting to %s(%s):%d",
	   root->hostname,
	   inet_ntoa (sin.sin_addr),
	   port);

    if (connect (s, (struct sockaddr *) &sin, sizeof sin) < 0)
	error (1, 0, "connect to %s(%s):%d failed: %s",
	       root->hostname,
	       inet_ntoa (sin.sin_addr),
	       port, SOCK_STRERROR (SOCK_ERRNO));

    {
	const char *realm;
	struct sockaddr_in laddr;
	int laddrlen;
	KTEXT_ST ticket;
	MSG_DAT msg_data;
	CREDENTIALS cred;
	int status;

	realm = krb_realmofhost (hname);

	laddrlen = sizeof (laddr);
	if (getsockname (s, (struct sockaddr *) &laddr, &laddrlen) < 0)
	    error (1, 0, "getsockname failed: %s", SOCK_STRERROR (SOCK_ERRNO));

	/* We don't care about the checksum, and pass it as zero.  */
	status = krb_sendauth (KOPT_DO_MUTUAL, s, &ticket, "rcmd",
			       hname, realm, (unsigned long) 0, &msg_data,
			       &cred, sched, &laddr, &sin, "KCVSV1.0");
	if (status != KSUCCESS)
	    error (1, 0, "kerberos authentication failed: %s",
		   krb_get_err_text (status));
	memcpy (kblock, cred.session, sizeof (C_Block));
    }

    close_on_exec (s);

    free (hname);

    /* Give caller the values it wants. */
    make_bufs_from_fds (s, s, 0, root, to_server_p, from_server_p, 1);
}
int
Verify (struct display *d, struct greet_info *greet, struct verify_info *verify)
{
	struct passwd	*p;
	login_cap_t	*lc;
	auth_session_t	*as;
	char		*style, *shell, *home, *s, **argv;
	char		path[MAXPATHLEN];
	int		authok;

	/* User may have specified an authentication style. */
	if ((style = strchr(greet->name, ':')) != NULL)
		*style++ = '\0';

	Debug ("Verify %s, style %s ...\n", greet->name,
	    style ? style : "default");

	p = getpwnam (greet->name);
	endpwent();

	if (!p || strlen (greet->name) == 0) {
		Debug("getpwnam() failed.\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	}

	if ((lc = login_getclass(p->pw_class)) == NULL) {
		Debug("login_getclass() failed.\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	}
	if ((style = login_getstyle(lc, style, "xdm")) == NULL) {
		Debug("login_getstyle() failed.\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	}
	if ((as = auth_open()) == NULL) {
		Debug("auth_open() failed.\n");
		login_close(lc);
		bzero(greet->password, strlen(greet->password));
		return 0;
	}
	if (auth_setoption(as, "login", "yes") == -1) {
		Debug("auth_setoption() failed.\n");
		login_close(lc);
		bzero(greet->password, strlen(greet->password));
		return 0;
	}

	/* Set up state for no challenge, just check a response. */
	auth_setstate(as, 0);
	auth_setdata(as, "", 1);
	auth_setdata(as, greet->password, strlen(greet->password) + 1);

	/* Build path of the auth script and call it */
	snprintf(path, sizeof(path), _PATH_AUTHPROG "%s", style);
	auth_call(as, path, style, "-s", "response", greet->name, 
		  lc->lc_class, (void *)NULL);
	authok = auth_getstate(as);

	if ((authok & AUTH_ALLOW) == 0) {
		Debug("password verify failed\n");
		bzero(greet->password, strlen(greet->password));
		auth_close(as);
		login_close(lc);
		return 0;
	}
	/* Run the approval script */
	if (!auth_approval(as, lc, greet->name, "auth-xdm")) {
		Debug("login not approved\n");
		bzero(greet->password, strlen(greet->password));
		auth_close(as);
		login_close(lc);
		return 0;
	}
	auth_close(as);
	login_close(lc);
	/* Check empty passwords against allowNullPasswd */
	if (!greet->allow_null_passwd && strlen(greet->password) == 0) {
		Debug("empty password not allowed\n");
		return 0;
	}
	/* Only accept root logins if allowRootLogin resource is set */
	if (p->pw_uid == 0 && !greet->allow_root_login) {
		Debug("root logins not allowed\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	}

	/*
	 * Shell must be in /etc/shells 
	 */
	for (;;) {
		s = getusershell();
		if (s == NULL) {
			/* did not found the shell in /etc/shells 
			   -> failure */
			Debug("shell not in /etc/shells\n");
			bzero(greet->password, strlen(greet->password));
			endusershell();
			return 0;
		}
		if (strcmp(s, p->pw_shell) == 0) {
			/* found the shell in /etc/shells */
			endusershell();
			break;
		}
	} 
#else /* !USE_BSDAUTH */
int
Verify (struct display *d, struct greet_info *greet, struct verify_info *verify)
{
	struct passwd	*p;
#ifdef USE_PAM
	pam_handle_t **pamhp = thepamhp();
#else
#ifdef USESHADOW
	struct spwd	*sp;
#endif
	char		*user_pass = NULL;
#endif
#ifdef __OpenBSD__
	char            *s;
	struct timeval  tp;
#endif
	char		*shell, *home;
	char		**argv;

	Debug ("Verify %s ...\n", greet->name);

#if defined(sun) && defined(SVR4)
	/* Solaris: If CONSOLE is set to /dev/console in /etc/default/login, 
	   then root can only login on system console */

# define SOLARIS_LOGIN_DEFAULTS "/etc/default/login"

	if (strcmp(greet->name, "root") == 0) {
	    char *console = NULL, *tmp = NULL;
	    FILE *fs;

	    if ((fs= fopen(SOLARIS_LOGIN_DEFAULTS, "r")) != NULL)
	    {   
		char str[120];
		while (!feof(fs))
		{
		    fgets(str, 120, fs);
		    if(str[0] == '#' || strlen(str) < 8)
			continue;
		    if((tmp = strstr(str, "CONSOLE=")) != NULL)
			console = strdup((tmp+8));
		}
		fclose(fs);
                if ( console != NULL && 
		  (strncmp(console, "/dev/console", 12) == 0) && 
		  (strncmp(d->name,":0",2) != 0) )
		{
                        Debug("Not on system console\n");
                        bzero(greet->password, strlen(greet->password));
             		XFree(console); 
	                return 0;
                }
		XFree(console);	
	    }
	    else
	    {
		Debug("Could not open %s\n", SOLARIS_LOGIN_DEFAULTS);
	    }	
	}
#endif    

#ifndef USE_PAM
	p = getpwnam (greet->name);
	endpwent();

	if (!p || strlen (greet->name) == 0) {
		Debug ("getpwnam() failed.\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	} else {
#ifdef linux
	    if (!strcmp(p->pw_passwd, "!") || !strcmp(p->pw_passwd, "*")) {
		Debug ("The account is locked, no login allowed.\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	    }
#endif
	    user_pass = p->pw_passwd;
	}
#endif
#ifdef KERBEROS
	if(strcmp(greet->name, "root") != 0){
		char name[ANAME_SZ];
		char realm[REALM_SZ];
		char *q;
		int ret;
	    
		if(krb_get_lrealm(realm, 1)){
			Debug ("Can't get Kerberos realm.\n");
		} else {

		    sprintf(krbtkfile, "%s.%s", TKT_ROOT, d->name);
		    krb_set_tkt_string(krbtkfile);
		    unlink(krbtkfile);
           
		    ret = krb_verify_user(greet->name, "", realm, 
				      greet->password, 1, "rcmd");
           
		    if(ret == KSUCCESS){
			    chown(krbtkfile, p->pw_uid, p->pw_gid);
			    Debug("kerberos verify succeeded\n");
			    if (k_hasafs()) {
				    if (k_setpag() == -1)
					    LogError ("setpag() failed for %s\n",
						      greet->name);
				    
				    if((ret = k_afsklog(NULL, NULL)) != KSUCCESS)
					    LogError("Warning %s\n", 
						     krb_get_err_text(ret));
			    }
			    goto done;
		    } else if(ret != KDC_PR_UNKNOWN && ret != SKDC_CANT){
			    /* failure */
			    Debug("kerberos verify failure %d\n", ret);
			    krbtkfile[0] = '\0';
		    }
		}
	}
#endif
#ifndef USE_PAM
#ifdef USESHADOW
	errno = 0;
	sp = getspnam(greet->name);
	if (sp == NULL) {
	    Debug ("getspnam() failed, errno=%d.  Are you root?\n", errno);
	} else {
	    user_pass = sp->sp_pwdp;
	}
#ifndef QNX4
	endspent();
#endif  /* QNX4 doesn't need endspent() to end shadow passwd ops */
#endif
#if defined(ultrix) || defined(__ultrix__)
	if (authenticate_user(p, greet->password, NULL) < 0)
#else
	if (strcmp (crypt (greet->password, user_pass), user_pass))
#endif
	{
		if(!greet->allow_null_passwd || strlen(p->pw_passwd) > 0) {
			Debug ("password verify failed\n");
			bzero(greet->password, strlen(greet->password));
			return 0;
		} /* else: null passwd okay */
	}
#ifdef KERBEROS
done:
#endif
#ifdef __OpenBSD__
	/*
	 * Only accept root logins if allowRootLogin resource is set
	 */
	if ((p->pw_uid == 0) && !greet->allow_root_login) {
		Debug("root logins not allowed\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	}
	/*
	 * Shell must be in /etc/shells 
	 */
	for (;;) {
		s = getusershell();
		if (s == NULL) {
			/* did not found the shell in /etc/shells 
			   -> failure */
			Debug("shell not in /etc/shells\n");
			bzero(greet->password, strlen(greet->password));
			endusershell();
			return 0;
		}
		if (strcmp(s, p->pw_shell) == 0) {
			/* found the shell in /etc/shells */
			endusershell();
			break;
		}
	} 
	/*
	 * Test for expired password
	 */
	if (p->pw_change || p->pw_expire)
		(void)gettimeofday(&tp, (struct timezone *)NULL);
	if (p->pw_change) {
		if (tp.tv_sec >= p->pw_change) {
			Debug("Password has expired.\n");
			bzero(greet->password, strlen(greet->password));
			return 0;
		}
	}
	if (p->pw_expire) {
		if (tp.tv_sec >= p->pw_expire) {
			Debug("account has expired.\n");
			bzero(greet->password, strlen(greet->password));
			return 0;
		} 
	}
#endif /* __OpenBSD__ */
	bzero(user_pass, strlen(user_pass)); /* in case shadow password */

#else /* USE_PAM */
#define PAM_BAIL	\
	if (pam_error != PAM_SUCCESS) goto pam_failed;

	PAM_password = greet->password;
	pam_error = pam_start("xdm", greet->name, &PAM_conversation, pamhp);
	PAM_BAIL;
	pam_error = pam_set_item(*pamhp, PAM_TTY, d->name);
	PAM_BAIL;
	pam_error = pam_set_item(*pamhp, PAM_RHOST, "");
	PAM_BAIL;
	pam_error = pam_authenticate(*pamhp, 0);
	PAM_BAIL;
	pam_error = pam_acct_mgmt(*pamhp, 0);
	/* really should do password changing, but it doesn't fit well */
	PAM_BAIL;
	pam_error = pam_setcred(*pamhp, 0);
	PAM_BAIL;
	p = getpwnam (greet->name);
	endpwent();

	if (!p || strlen (greet->name) == 0) {
		Debug ("getpwnam() failed.\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	}

	if (pam_error != PAM_SUCCESS) {
	pam_failed:
		pam_end(*pamhp, PAM_SUCCESS);
		*pamhp = NULL;
		return 0;
	}
#undef PAM_BAIL
#endif /* USE_PAM */
#endif /* USE_BSDAUTH */

	Debug ("verify succeeded\n");
	/* The password is passed to StartClient() for use by user-based
	   authorization schemes.  It is zeroed there. */
	verify->uid = p->pw_uid;
	verify->gid = p->pw_gid;
	home = p->pw_dir;
	shell = p->pw_shell;
	argv = 0;
	if (d->session)
		argv = parseArgs (argv, d->session);
	if (greet->string)
		argv = parseArgs (argv, greet->string);
	if (!argv)
		argv = parseArgs (argv, "xsession");
	verify->argv = argv;
	verify->userEnviron = userEnv (d, p->pw_uid == 0,
				       greet->name, home, shell);
	Debug ("user environment:\n");
	printEnv (verify->userEnviron);
	verify->systemEnviron = systemEnv (d, greet->name, home);
	Debug ("system environment:\n");
	printEnv (verify->systemEnviron);
	Debug ("end of environments\n");
	return 1;
}