summaryrefslogtreecommitdiffstats
path: root/eBones/libexec/rkinitd/krb.c
diff options
context:
space:
mode:
Diffstat (limited to 'eBones/libexec/rkinitd/krb.c')
-rw-r--r--eBones/libexec/rkinitd/krb.c388
1 files changed, 388 insertions, 0 deletions
diff --git a/eBones/libexec/rkinitd/krb.c b/eBones/libexec/rkinitd/krb.c
new file mode 100644
index 0000000..23734db
--- /dev/null
+++ b/eBones/libexec/rkinitd/krb.c
@@ -0,0 +1,388 @@
+/*
+ * $Id: krb.c,v 1.1 1993/07/29 22:45:19 dglo Exp gibbs $
+ * $Source: /usr/src/eBones/rkinitd/RCS/krb.c,v $
+ * $Author: dglo $
+ *
+ * This file contains all of the kerberos part of rkinitd.
+ */
+
+#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS)
+static char *rcsid = "$Id: krb.c,v 1.1 1993/07/29 22:45:19 dglo Exp gibbs $";
+#endif /* lint || SABER || LOCORE || RCS_HDRS */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <syslog.h>
+#include <netinet/in.h>
+#include <setjmp.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <krb.h>
+#include <des.h>
+
+#include <rkinit.h>
+#include <rkinit_private.h>
+#include <rkinit_err.h>
+
+#include "rkinitd.h"
+
+#define FAILURE (!RKINIT_SUCCESS)
+
+extern int errno;
+
+static char errbuf[BUFSIZ];
+
+typedef struct {
+ jmp_buf env;
+} rkinitd_intkt_info;
+
+
+#if defined(_AIX) && defined(_IBMR2)
+
+#include <sys/id.h>
+
+/*
+ * The RIOS has bizzarre ideas about changing uids around. They are
+ * such that the seteuid and setruid calls here fail. For this reason
+ * we are replacing the seteuid and setruid calls.
+ *
+ * The bizzarre ideas are as follows:
+ *
+ * The effective ID may be changed only to the current real or
+ * saved IDs.
+ *
+ * The saved uid may be set only if the real and effective
+ * uids are being set to the same value.
+ *
+ * The real uid may be set only if the effective
+ * uid is being set to the same value.
+ */
+
+#ifdef __STDC__
+static int setruid(uid_t ruid)
+#else
+static int setruid(ruid)
+ uid_t ruid;
+#endif /* __STDC__ */
+{
+ uid_t euid;
+
+ euid = geteuid();
+
+ if (setuidx(ID_REAL | ID_EFFECTIVE, ruid) == -1)
+ return (-1);
+
+ return (setuidx(ID_EFFECTIVE, euid));
+}
+
+
+#ifdef __STDC__
+static int seteuid(uid_t euid)
+#else
+static int seteuid(euid)
+ uid_t euid;
+#endif /* __STDC__ */
+{
+ uid_t ruid;
+
+ ruid = getuid();
+
+ if (setuidx(ID_SAVED | ID_REAL | ID_EFFECTIVE, euid) == -1)
+ return (-1);
+
+ return (setruid(ruid));
+}
+
+
+#ifdef __STDC__
+static int setreuid(uid_t ruid, uid_t euid)
+#else
+static int setreuid(ruid, euid)
+ uid_t ruid;
+ uid_t euid;
+#endif /* __STDC__ */
+{
+ if (seteuid(euid) == -1)
+ return (-1);
+
+ return (setruid(ruid));
+}
+
+
+#ifdef __STDC__
+static int setuid(uid_t uid)
+#else
+static int setuid(uid)
+ uid_t uid;
+#endif /* __STDC__ */
+{
+ return (setreuid(uid, uid));
+}
+
+#endif /* RIOS */
+
+
+#ifdef __STDC__
+static void this_phost(char *host, int hostlen)
+#else
+static void this_phost(host, hostlen)
+ char *host;
+ int hostlen;
+#endif /* __STDC__ */
+{
+ char this_host[MAXHOSTNAMELEN + 1];
+
+ BCLEAR(this_host);
+
+ if (gethostname(this_host, sizeof(this_host)) < 0) {
+ sprintf(errbuf, "gethostname: %s", sys_errlist[errno]);
+ rkinit_errmsg(errbuf);
+ error();
+ exit(1);
+ }
+
+ strncpy(host, krb_get_phost(this_host), hostlen - 1);
+}
+
+#ifdef __STDC__
+static int decrypt_tkt(char *user, char *instance, char *realm, char *arg,
+ int (*key_proc)(), KTEXT *cipp)
+#else
+static int decrypt_tkt(user, instance, realm, arg, key_proc, cipp)
+ char *user;
+ char *instance;
+ char *realm;
+ char *arg;
+ int (*key_proc)();
+ KTEXT *cipp;
+#endif /* __STDC__ */
+{
+ MSG_DAT msg_data; /* Message data containing decrypted data */
+ KTEXT_ST auth; /* Authenticator */
+ AUTH_DAT auth_dat; /* Authentication data */
+ KTEXT cip = *cipp;
+ MSG_DAT scip;
+ int status = 0;
+ des_cblock key;
+ des_key_schedule sched;
+ char phost[MAXHOSTNAMELEN + 1];
+ struct sockaddr_in caddr; /* client internet address */
+ struct sockaddr_in saddr; /* server internet address */
+
+ rkinitd_intkt_info *rii = (rkinitd_intkt_info *)arg;
+
+ u_char enc_data[MAX_KTXT_LEN];
+
+ SBCLEAR(auth);
+ SBCLEAR(auth_dat);
+ SBCLEAR(scip);
+ BCLEAR(enc_data);
+
+ scip.app_data = enc_data;
+
+ /*
+ * Exchange with the client our response from the KDC (ticket encrypted
+ * in user's private key) for the same ticket encrypted in our
+ * (not yet known) session key.
+ */
+
+ rpc_exchange_tkt(cip, &scip);
+
+ /*
+ * Get the authenticator
+ */
+
+ SBCLEAR(auth);
+
+ rpc_getauth(&auth, &caddr, &saddr);
+
+ /*
+ * Decode authenticator and extract session key. The first zero
+ * means we don't care what host this comes from. This needs to
+ * be done with euid of root so that /etc/srvtab can be read.
+ */
+
+ BCLEAR(phost);
+ this_phost(phost, sizeof(phost));
+
+ /*
+ * This function has to use longjmp to return to the caller
+ * because the kerberos library routine that calls it doesn't
+ * pay attention to the return value it gives. That means that
+ * if any of these routines failed, the error returned to the client
+ * would be "password incorrect".
+ */
+
+ if ((status = krb_rd_req(&auth, KEY, phost, caddr.sin_addr.s_addr,
+ &auth_dat, KEYFILE))) {
+ sprintf(errbuf, "krb_rd_req: %s", krb_err_txt[status]);
+ rkinit_errmsg(errbuf);
+ longjmp(rii->env, status);
+ }
+
+ bcopy(auth_dat.session, key, sizeof(key));
+ if (des_key_sched(&key, sched)) {
+ sprintf(errbuf, "Error in des_key_sched");
+ rkinit_errmsg(errbuf);
+ longjmp(rii->env, RKINIT_DES);
+ }
+
+ /* Decrypt the data. */
+ if ((status =
+ krb_rd_priv((u_char *)scip.app_data, scip.app_length,
+ sched, key, &caddr, &saddr, &msg_data)) == KSUCCESS) {
+ cip->length = msg_data.app_length;
+ bcopy(msg_data.app_data, cip->dat, msg_data.app_length);
+ cip->dat[cip->length] = 0;
+ }
+ else {
+ sprintf(errbuf, "krb_rd_priv: %s", krb_err_txt[status]);
+ rkinit_errmsg(errbuf);
+ longjmp(rii->env, status);
+ }
+
+ return(status);
+}
+
+#ifdef __STDC__
+static int validate_user(char *aname, char *inst, char *realm,
+ char *username, char *errmsg)
+#else
+static int validate_user(aname, inst, realm, username, errmsg)
+ char *aname;
+ char *inst;
+ char *realm;
+ char *username;
+ char *errmsg;
+#endif /* __STDC__ */
+{
+ struct passwd *pwnam; /* For access_check and uid */
+ AUTH_DAT auth_dat;
+ int kstatus = KSUCCESS;
+
+ SBCLEAR(auth_dat);
+
+ if ((pwnam = getpwnam(username)) == NULL) {
+ sprintf(errmsg, "%s does not exist on the remote host.", username);
+ return(FAILURE);
+ }
+
+ strcpy(auth_dat.pname, aname);
+ strcpy(auth_dat.pinst, inst);
+ strcpy(auth_dat.prealm, realm);
+
+ if (seteuid(pwnam->pw_uid) < 0) {
+ sprintf(errmsg, "Failure setting euid to %d: %s\n", pwnam->pw_uid,
+ sys_errlist[errno]);
+ strcpy(errbuf, errmsg);
+ error();
+ return(FAILURE);
+ }
+ kstatus = kuserok(&auth_dat, username);
+ if (seteuid(0) < 0) {
+ sprintf(errmsg, "Failure setting euid to 0: %s\n",
+ sys_errlist[errno]);
+ strcpy(errbuf, errmsg);
+ error();
+ return(FAILURE);
+ }
+
+ if (kstatus != KSUCCESS) {
+ sprintf(errmsg, "%s has not allowed you to log in with", username);
+ if (strlen(auth_dat.pinst))
+ sprintf(errmsg, "%s %s.%s", errmsg, auth_dat.pname,
+ auth_dat.pinst);
+ else
+ sprintf(errmsg, "%s %s", errmsg, auth_dat.pname);
+ sprintf(errmsg, "%s@%s tickets.", errmsg, auth_dat.prealm);
+ return(FAILURE);
+ }
+
+ /*
+ * Set real uid to owner of ticket file. The library takes care
+ * of making the appropriate change.
+ */
+ if (setruid(pwnam->pw_uid) < 0) {
+ sprintf(errmsg, "Failure setting ruid to %d: %s\n", pwnam->pw_uid,
+ sys_errlist[errno]);
+ strcpy(errbuf, errmsg);
+ error();
+ return(FAILURE);
+ }
+
+ return(RKINIT_SUCCESS);
+}
+
+#ifdef __STDC__
+int get_tickets(int version)
+#else
+int get_tickets(version)
+ int version;
+#endif /* __STDC__ */
+{
+ rkinit_info info;
+ AUTH_DAT auth_dat;
+
+ int status;
+ char errmsg[BUFSIZ]; /* error message for client */
+
+ rkinitd_intkt_info rii;
+
+ SBCLEAR(info);
+ SBCLEAR(auth_dat);
+ BCLEAR(errmsg);
+ SBCLEAR(rii);
+
+ rpc_get_rkinit_info(&info);
+
+ /*
+ * The validate_user routine makes sure that the principal in question
+ * is allowed to log in as username, and if so, does a setuid(localuid).
+ * If there is an access violation or an error in setting the uid,
+ * an error is returned and the string errmsg is initialized with
+ * an error message that will be sent back to the client.
+ */
+ if ((status = validate_user(info.aname, info.inst, info.realm,
+ info.username, errmsg)) != RKINIT_SUCCESS) {
+ rpc_send_error(errmsg);
+ exit(0);
+ }
+ else
+ rpc_send_success();
+
+ /*
+ * If the name of a ticket file was specified, set it; otherwise,
+ * just use the default.
+ */
+ if (strlen(info.tktfilename))
+ krb_set_tkt_string(info.tktfilename);
+
+ /*
+ * Call internal kerberos library routine so that we can supply
+ * our own ticket decryption routine.
+ */
+
+ /*
+ * We need a setjmp here because krb_get_in_tkt ignores the
+ * return value of decrypt_tkt. Thus if we want any of its
+ * return values to reach the client, we have to jump out of
+ * the routine.
+ */
+
+ if (setjmp(rii.env) == 0) {
+ if ((status = krb_get_in_tkt(info.aname, info.inst, info.realm,
+ info.sname, info.sinst, info.lifetime,
+ NULL, decrypt_tkt, (char *)&rii))) {
+ strcpy(errmsg, krb_err_txt[status]);
+ rpc_send_error(errmsg);
+ }
+ else
+ rpc_send_success();
+ }
+ else
+ rpc_send_error(errbuf);
+
+ return(RKINIT_SUCCESS);
+}
OpenPOWER on IntegriCloud