exec_prefix = @exec_prefix@
sbindir = @sbindir@
-COBJS = identd.o parse.o kernel.o kernel_helper.o kvm.o ident_auth.o \
- tables.o gssapi.o @LIBOBJS@
+COBJS = identd.o parse.o ident_auth.o tables.o gssapi.o @LIBOBJS@
+KOBJS = kernel.o kernel_helper.o pkvm.o
all: sidentd
-sidentd: $(COBJS)
- $(CC) $(LDFLAGS) -o sidentd $(COBJS) $(LIBS)
+sidentd: $(COBJS) $(KOBJS)
+ $(CC) $(LDFLAGS) -o sidentd $(COBJS) $(KOBJS) $(LIBS)
-kernel.o: kernel.c identd.h error.h kernel/kvm.h Makefile
+kernel.o: kernel.c pidentd.h pkvm.h Makefile
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o kernel.o kernel.c
-libkvm.a: kvm.o
- @rm -f libkvm.a
- ar cq libkvm.a kvm.o
-
-itest: itest.o kernel.o kvm.o
- $(CC) $(LDFLAGS) -o itest itest.o kernel.o kernel_helper.o kvm.o $(LIBS)
+itest: itest.o $(KOBJS)
+ $(CC) $(LDFLAGS) -o itest itest.o $(KOBJS) $(LIBS)
clean:
rm -f sidentd core *.o kernel/*.o
# DO NOT DELETE THIS LINE -- make depend depends on it.
-gssapi.o: gssapi.c identd.h $(top_srcdir)/include/sident.h \
- $(top_builddir)/config.h
+gssapi.o: gssapi.c identd.h $(top_builddir)/config.h \
+ $(top_srcdir)/include/sident.h
ident_auth.o: ident_auth.c $(top_builddir)/config.h identd.h \
- $(top_srcdir)/include/sident.h
-identd.o: identd.c error.h identd.h $(top_srcdir)/include/sident.h \
- $(top_builddir)/config.h paths.h
-itest.o: itest.c identd.h $(top_srcdir)/include/sident.h \
- $(top_builddir)/config.h error.h pidentd.h
+ $(top_srcdir)/include/sident.h
+identd.o: identd.c identd.h $(top_builddir)/config.h \
+ $(top_srcdir)/include/sident.h
+itest.o: itest.c identd.h $(top_builddir)/config.h \
+ $(top_srcdir)/include/sident.h pidentd.h
kernel.o: kernel.c $(top_builddir)/config.h pidentd.h
-kernel_helper.o: kernel_helper.c $(top_builddir)/config.h pidentd.h
-kvm.o: kvm.c $(top_builddir)/config.h
-parse.o: parse.c error.h identd.h $(top_srcdir)/include/sident.h \
- $(top_builddir)/config.h pidentd.h
+kernel_helper.o: kernel_helper.c $(top_builddir)/config.h identd.h \
+ $(top_srcdir)/include/sident.h pidentd.h
+lifetime.o: lifetime.c
+parse.o: parse.c identd.h $(top_builddir)/config.h \
+ $(top_srcdir)/include/sident.h pidentd.h
pkvm.o: pkvm.c $(top_builddir)/config.h
tables.o: tables.c
+++ /dev/null
-/** @file
- * Error handling macros.
- *
- * This program is in the public domain and may be used freely by anyone who
- * wants it.
- *
- * @date Last updated 1992-Aug-19
- * @author Peter Eriksson <pen@lysator.liu.se>
- *
- * $Id$
- */
-
-#ifndef ERROR_H
-#define ERROR_H 1
-
-#include <syslog.h>
-
-#define ERROR(fmt) \
- ((syslog_flag ? (syslog(LOG_ERR, fmt),0) : 0), \
- (debug_flag ? (fprintf(stderr, "%d , %d : ERROR : X-DBG : ", \
- lport, fport), \
- fprintf(stderr, fmt), perror(": "), 0) : \
- (printf("%d , %d : ERROR : UNKNOWN-ERROR\r\n", lport, fport), 0)), \
- fflush(stdout), fflush(stderr), exit(1), 0)
-
-
-#define ERROR1(fmt,v1) \
- ((syslog_flag ? (syslog(LOG_ERR, fmt, v1),0) : 0), \
- (debug_flag ? (fprintf(stderr, "%d , %d : ERROR : X-DBG : ", \
- lport, fport), \
- fprintf(stderr, fmt, v1), perror(": "), 0) : \
- (printf("%d , %d : ERROR : UNKNOWN-ERROR\r\n", lport, fport), 0)), \
- fflush(stdout), fflush(stderr), exit(1), 0)
-
-#define ERROR2(fmt,v1,v2) \
- ((syslog_flag ? (syslog(LOG_ERR, fmt, v1, v2),0) : 0), \
- (debug_flag ? (fprintf(stderr, "%d , %d : ERROR : X-DBG : ", \
- lport, fport), \
- fprintf(stderr, fmt, v1, v2), perror(": "), 0) : \
- (printf("%d , %d : ERROR : UNKNOWN-ERROR\r\n", lport, fport), 0)), \
- fflush(stdout), fflush(stderr), exit(1), 0)
-
-#endif /* ERROR_H */
* @date 1996-08-28
*
* $Id$
+ *
+ * Much of this code was originally taken from acte_krb.c in the Cyrus IMAP
+ * distribution. At the time, the copyright and license statement was as
+ * follows:
+ *
+ * (C) Copyright 1994 by Carnegie Mellon University
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Carnegie Mellon University not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Carnegie Mellon University
+ * makes no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.h"
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
-#include <pwd.h>
+#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
-#include <sys/socket.h>
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <syslog.h>
-#include <krb.h>
+#ifdef HAVE_KERBEROSIV_KRB_H
+# include <kerberosIV/krb.h>
+#else
+# include <krb.h>
+#endif
-#include "identd.h"
+#include "identd.h"
/* Exported definition of responder authentication mechanism */
-static int krb_responder_start();
-static int null_responder_start();
-static int krb_responder_auth();
-static int null_responder_auth();
-static void krb_free_state();
-static void null_free_state();
-static int trivial_responder_start();
+static int krb_responder_start();
+static int null_responder_start();
+static int krb_responder_auth();
+static int null_responder_auth();
+static void krb_free_state();
+static void null_free_state();
+static int trivial_responder_start();
static int trivial_responder_auth();
extern int do_out();
null_free_state
};
-
#define IDENT_METHODS_COUNT 4
-/* TRIVIAL method must always be the last method */
-#define IDENT_TRIVIAL_METHOD (IDENT_METHODS_COUNT - 1 )
-struct ident_responder_auth *auth_methods[IDENT_METHODS_COUNT] = { &krb_ident_auth,
- &gssapi_ident_auth,
- &otp_ident_auth,
- &trivial_ident_auth
-};
-
-int
-parse_auth(line,auth_struct)
-char *line;
-struct ident_responder_auth **auth_struct ;
-{
- int rcode ;
- int i ;
- char auth_method[128] ;
- *auth_struct = NULL ;
- if ( line == NULL ) {
- *auth_struct = auth_methods[IDENT_TRIVIAL_METHOD] ;
- return IDENT_AUTH_OKAY ;
- }
- /* Grok to the next , */
-
- rcode = sscanf(line ," %32[^ \t\n\r,]",auth_method );
-
-
- for(i = 0 ; i < IDENT_METHODS_COUNT ; i++ ) {
- if ( strncmp(auth_method,auth_methods[i]->auth_method,
- strlen(auth_methods[i]->auth_method)) == 0 ) {
- *auth_struct = auth_methods[i] ;
- return(IDENT_AUTH_OKAY) ;
- }
- }
- return(IDENT_INVALID_REQ_INFO);
-
-
-}
+/* TRIVIAL method must always be the last method */
+#define IDENT_TRIVIAL_METHOD (IDENT_METHODS_COUNT - 1 )
-/* All the code from here to EOF is C&P from imclient.c in the imap.1.4
-libraries.
-*/
+struct ident_responder_auth *auth_methods[IDENT_METHODS_COUNT] = {
+ &krb_ident_auth, &gssapi_ident_auth, &otp_ident_auth, &trivial_ident_auth
+};
-#define XX 127
-/*
- * Tables for encoding/decoding base64
+/** Given a line from a requester, find the requested auth type.
+ *
+ * If the line is NULL, assume the trivial (traditional) method. Otherwise,
+ * find a case-sensitive match for the authentication method given in the
+ * table of acceptable authentication methods. Set auth_struct to the struct
+ * for the one found.
+ *
+ * @param line The input from the requester.
+ * @param auth_struct Set to the struct corresponding to the desired method.
+ * @return An error code or #IDENT_AUTH_OKAY.
*/
+int
+parse_auth(char *line, struct ident_responder_auth **auth_struct)
+{
+ int i, rcode;
+ char auth_method[128];
+ const char *method;
+
+ *auth_struct = NULL;
+ if (line == NULL) {
+ *auth_struct = auth_methods[IDENT_TRIVIAL_METHOD];
+ return IDENT_AUTH_OKAY;
+ }
+
+ /* Parse the line to find the authentication method. */
+ rcode = sscanf(line, " %32[^ \t\n\r,]", auth_method);
+ if (rcode != 1)
+ return IDENT_INVALID_REQ_INFO;
+ for (i = 0; i < IDENT_METHODS_COUNT; i++) {
+ method = auth_methods[i]->auth_method;
+ if (strncmp(auth_method, method, strlen(method)) == 0) {
+ *auth_struct = auth_methods[i];
+ return IDENT_AUTH_OKAY;
+ }
+ }
+ return IDENT_INVALID_REQ_INFO;
+}
+
+
+/* Tables for encoding and decoding base64. */
static const char basis_64[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#define XX 127
static const char index_64[256] = {
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
};
#define CHAR64(c) (index_64[(unsigned char)(c)])
-/*
- * Decode in-place the base64 data in 'input'. Returns the length
- * of the decoded data, or -1 if there was an error.
+/** Decode in-place a buffer encoded in base64.
+ *
+ * @param input The buffer containing base64 data to decode.
+ * @return Length of the decoded data, or -1 on error.
*/
-int
-ident_decodebase64(input)
-char *input;
+int
+ident_decodebase64(char *input)
{
int len = 0;
unsigned char *output = (unsigned char *)input;
int c1, c2, c3, c4;
while (*input) {
- c1 = *input++;
- if (CHAR64(c1) == XX) return -1;
- c2 = *input++;
- if (CHAR64(c2) == XX) return -1;
- c3 = *input++;
- if (c3 != '=' && CHAR64(c3) == XX) return -1;
- c4 = *input++;
- if (c4 != '=' && CHAR64(c4) == XX) return -1;
- *output++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4);
- ++len;
- if (c3 == '=') break;
- *output++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2);
- ++len;
- if (c4 == '=') break;
- *output++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4);
- ++len;
+ c1 = *input++;
+ if (CHAR64(c1) == XX)
+ return -1;
+ c2 = *input++;
+ if (CHAR64(c2) == XX)
+ return -1;
+ c3 = *input++;
+ if (c3 != '=' && CHAR64(c3) == XX)
+ return -1;
+ c4 = *input++;
+ if (c4 != '=' && CHAR64(c4) == XX)
+ return -1;
+ *output++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4);
+ ++len;
+ if (c3 == '=')
+ break;
+ *output++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2);
+ ++len;
+ if (c4 == '=')
+ break;
+ *output++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4);
+ ++len;
}
return len;
}
-
-/*
- * Write to the string 'output' the base-64 encoded data
- * 'input', of (unencoded) length 'len'.
+/** Encode data into base64.
+ *
+ * The output buffer must be long enough to hold the encoded input.
+ *
+ * @param input Data to encode.
+ * @param output Buffer into which to write the encoded data.
+ * @param len The length of the input (not the size of the output buffer).
*/
-
void
-ident_writebase64(input, output, len)
-char *input;
-char *output;
-int len;
+ident_writebase64(char *input, char *output, int len)
{
char buf[IDENT_BUFFER_SIZE];
- char *outptr ;
+ char *outptr;
int buflen = 0;
int c1, c2, c3;
- outptr = output ;
- while (len) {
- if (buflen >= sizeof(buf)-4) {
- strncpy(outptr,buf,buflen);
- buflen = 0;
- outptr += buflen ;
- }
-
- c1 = (unsigned char)*input++;
- buf[buflen++] = basis_64[c1>>2];
-
- if (--len == 0) c2 = 0;
- else c2 = (unsigned char)*input++;
- buf[buflen++] = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)];
-
- if (len == 0) {
- buf[buflen++] = '=';
- buf[buflen++] = '=';
- break;
- }
-
- if (--len == 0) c3 = 0;
- else c3 = (unsigned char)*input++;
-
- buf[buflen++] = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
- if (len == 0) {
- buf[buflen++] = '=';
- break;
- }
-
- --len;
- buf[buflen++] = basis_64[c3 & 0x3F];
- }
- if (buflen >= sizeof(buf)-2) {
- strncpy(outptr, buf, buflen);
- outptr += buflen ;
- buflen = 0;
- }
- buf[buflen++] = '\0';
- strcpy(outptr, buf);
-}
+ outptr = output;
+ while (len > 0) {
+ if (buflen >= sizeof(buf) - 4) {
+ strncpy(outptr, buf, buflen);
+ buflen = 0;
+ outptr += buflen;
+ }
-/*
-**
-** Kerberos auth routines
-**
-**
-*/
+ c1 = (unsigned char) *input++;
+ buf[buflen++] = basis_64[c1 >> 2];
+ if (--len == 0)
+ c2 = 0;
+ else
+ c2 = (unsigned char) *input++;
+ buf[buflen++] = basis_64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)];
-/* acte_krb.c -- KERBEROS_V4 authentication routines for IMAP.
- *
- * (C) Copyright 1994 by Carnegie Mellon University
- *
- * All Rights Reserved
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without
- * fee, provided that the above copyright notice appear in all copies
- * and that both that copyright notice and this permission notice
- * appear in supporting documentation, and that the name of Carnegie
- * Mellon University not be used in advertising or publicity
- * pertaining to distribution of the software without specific,
- * written prior permission. Carnegie Mellon University makes no
- * representations about the suitability of this software for any
- * purpose. It is provided "as is" without express or implied
- * warranty.
- *
- * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
- * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- *
- */
+ if (len == 0) {
+ buf[buflen++] = '=';
+ buf[buflen++] = '=';
+ break;
+ }
+
+ if (--len == 0)
+ c3 = 0;
+ else
+ c3 = (unsigned char) *input++;
+ buf[buflen++] = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)];
+
+ if (len == 0) {
+ buf[buflen++] = '=';
+ break;
+ }
-extern char *lcase();
-extern char *krb_get_phost(), *krb_realmofhost();
+ --len;
+ buf[buflen++] = basis_64[c3 & 0x3F];
+ }
-/* Maximum number of bytes of overhead the protection mechanisms use */
-#define PROTECTION_OVERHEAD 31
+ if (buflen >= sizeof(buf) - 2) {
+ strncpy(outptr, buf, buflen);
+ outptr += buflen;
+ buflen = 0;
+ }
+ buf[buflen++] = '\0';
+ strcpy(outptr, buf);
+}
/* Private state used by this mechanism */
struct krb_state {
- /* common */
- char service[MAX_K_NAME_SZ+1];
+ char service[MAX_K_NAME_SZ + 1];
int authstepno;
- des_cblock session; /* Our session key */
- des_key_schedule schedule; /* Schedule for our session key */
+ des_cblock session; /* Our session key */
+ des_key_schedule schedule; /* Schedule for our session key */
int32_t challenge;
- char user[MAX_K_NAME_SZ+1];
- int protallowed;
- int maxbufsize;
- struct sockaddr_in localaddr, remoteaddr;
- long prot_time_sec;
- char prot_time_5ms;
- /* client */
+
+ /* Used by client. */
char instance[INST_SZ];
char realm[REALM_SZ];
- /* server */
- int (*authproc)();
- AUTH_DAT kdata;
};
-/*
- * Free the space used by an opaque state pointer
+/** Free the space used by the opaque mechanism state pointer.
+ *
+ * @param state Pointer to free.
*/
static void
-krb_free_state(state)
-void *state;
+krb_free_state(void *state)
{
- memset((char *)state, 0, sizeof(struct krb_state));
- free((char *) state);
+ memset(state, 0, sizeof(struct krb_state));
+ free(state);
}
-static int krb_is_ticket(tf_name,auth_data)
- char *tf_name;
- struct ident_auth_data *auth_data;
+/** Check whether a file is a valid ticket for our user of interest.
+ *
+ * @param tf_name The name of the file to check.
+ * @param auth_data Data about the authentication we're attempting.
+ * @return Returns a Kerberos status code (KSUCCESS on success).
+ */
+static int
+krb_is_ticket(char *tf_name, struct ident_auth_data *auth_data)
{
- struct stat stat_buf;
- int code ;
- char pname[ANAME_SZ];
- char pinst[INST_SZ];
- CREDENTIALS cred;
- time_t now;
-
- if (lstat(tf_name, &stat_buf) < 0) {
- if ( debug_flag && syslog_flag ) {
- syslog(LOG_DEBUG,"lstat error %d on %s",errno,tf_name);
- }
-
- switch (errno) {
- case ENOENT:
- return NO_TKT_FIL;
- default:
- return TKT_FIL_ACC;
- }
- }
-
- /* Check ownership */
- if (stat_buf.st_uid != auth_data->uid ) {
- if ( debug_flag && syslog_flag ) {
- syslog(LOG_DEBUG,"UID mismatch %d : %d on %s",stat_buf.st_uid,auth_data->uid,tf_name);
- }
- return TKT_FIL_ACC;
- }
- /* Check file perms for 600 */
- if ( (stat_buf.st_mode & S_IRUSR) != S_IRUSR ) {
- if ( debug_flag && syslog_flag ) {
- syslog(LOG_DEBUG,"User can't read %s",tf_name);
- }
-
- return TKT_FIL_ACC ;
- }
-
- if (
- ((stat_buf.st_mode & S_IRGRP) == S_IRGRP) ||
- ((stat_buf.st_mode & S_IWGRP) == S_IWGRP) ||
- ((stat_buf.st_mode & S_IROTH) == S_IROTH)||
- ((stat_buf.st_mode & S_IWOTH) == S_IWOTH) ) {
-
- if (syslog_flag ) {
- syslog(LOG_ALERT,"Incorrect file permissons on %s : %o",tf_name,stat_buf.st_mode);
- }
- return TKT_FIL_ACC ;
- }
- /* Okay now we should have a valid tkt file, let's look */
- /* Following src is C&P from klist.c in krb4. */
-
- /* Open ticket file */
- code = tf_init(tf_name, R_TKT_FIL);
- if ( code != KSUCCESS ) {
- tf_close() ;
- if ( debug_flag && syslog_flag ) {
- syslog(LOG_DEBUG,"tf_init failed %s",tf_name);
- }
-
- return code ;
- }
- /* Get principal name and instance */
- if ((code = tf_get_pname(pname)) ||
- (code = tf_get_pinst(pinst))) {
- tf_close () ;
- return code ;
- }
-
- /* Ensure ticket is valid */
- now = time(NULL);
- while (tf_get_cred(&cred) == KSUCCESS) {
- if (strcmp(cred.service,"krbtgt"))
- continue;
-#ifdef SHORT_LIFETIME
- cred.issue_date += ((unsigned char) cred.lifetime) * 5 * 60;
-#else
- cred.issue_date = krb_life_to_time(cred.issue_date, cred.lifetime);
-#endif
- if (now - cred.issue_date > 1 ) {
- tf_close () ;
- return KFAILURE ;
- }
- }
- tf_close() ;
- if ( syslog_flag ) {
- syslog(LOG_INFO,"Ticket file %s : %s.%s for %d",tf_name,pname,pinst,auth_data->uid );
- }
-
- return KSUCCESS ;
-}
+ struct stat stat_buf;
+ int code;
+ char pname[ANAME_SZ];
+ char pinst[INST_SZ];
+ CREDENTIALS cred;
+ time_t now;
+
+ /* Can we even stat the file? */
+ if (lstat(tf_name, &stat_buf) < 0) {
+ if (debug_flag && syslog_flag)
+ syslog(LOG_DEBUG, "lstat error %d on %s", errno, tf_name);
+ return (errno == ENOENT) ? NO_TKT_FIL : TKT_FIL_ACC;
+ }
+ /* Check ownership */
+ if (stat_buf.st_uid != auth_data->uid ) {
+ if (debug_flag && syslog_flag)
+ syslog(LOG_DEBUG, "UID mismatch %d : %d on %s", stat_buf.st_uid,
+ auth_data->uid, tf_name);
+ return TKT_FIL_ACC;
+ }
-static int krb_find_ticket(tktstring,auth_data)
- char *tktstring;
- struct ident_auth_data *auth_data;
-{
- int rcode ;
- char temp[MAXPATHLEN];
- /* this is OS depedent */
- DIR *temp_dir ;
- struct dirent *dp ;
-
- /* Need to set tkt file here */
- /* This is cheating we need to dive kernel and get TKTFILE from ENV */ /* try krb4 standard */
- sprintf(tktstring, "/tmp/tkt%d", auth_data->uid);
-
- rcode = krb_is_ticket(tktstring,auth_data) ;
- if (rcode == KSUCCESS ) {
- return IDENT_AUTH_OKAY ;
- }
-
- /* Now we will try grupping through /tmp for a "ticket file" */
-
- temp_dir = opendir("/tmp") ;
-
- for (dp = readdir(temp_dir); dp != NULL; dp = readdir(temp_dir)){
- if ( strncmp(dp->d_name, "tkt",strlen("tkt")) == 0 ) {
- if (strlen(dp->d_name) >= MAXPATHLEN-6)
- continue;
- sprintf(temp,"/tmp/%s",dp->d_name);
- rcode = krb_is_ticket(temp,auth_data);
- if (rcode == KSUCCESS ) {
- strncpy(tktstring,temp,MAXPATHLEN-1);
- closedir(temp_dir);
- return IDENT_AUTH_OKAY ;
- }
- if (syslog_flag && debug_flag ){
- syslog(LOG_DEBUG,"Rejected %s : %d",dp->d_name,rcode);
- }
-
+ /* Check file perms for 600. */
+ if ((stat_buf.st_mode & S_IRUSR) != S_IRUSR) {
+ if (debug_flag && syslog_flag)
+ syslog(LOG_DEBUG, "User can't read %s", tf_name);
+ return TKT_FIL_ACC;
+ }
+ if ( ((stat_buf.st_mode & S_IRGRP) == S_IRGRP)
+ || ((stat_buf.st_mode & S_IWGRP) == S_IWGRP)
+ || ((stat_buf.st_mode & S_IROTH) == S_IROTH)
+ || ((stat_buf.st_mode & S_IWOTH) == S_IWOTH)) {
+ if (syslog_flag)
+ syslog(LOG_ALERT, "Incorrect file permissons on %s : %o",
+ tf_name, stat_buf.st_mode);
+ return TKT_FIL_ACC ;
}
- }
- closedir(temp_dir);
+ /* Okay now we should have a valid ticket file. Let's look. The
+ following was mostly taken directly from klist.c in Kerberos v4. */
- return IDENT_USER_CANT_AUTH ;
-}
+ /* Open ticket file */
+ code = tf_init(tf_name, R_TKT_FIL);
+ if (code != KSUCCESS) {
+ tf_close();
+ if (debug_flag && syslog_flag)
+ syslog(LOG_DEBUG, "tf_init failed %s", tf_name);
+ return code;
+ }
+ /* Get principal name and instance. */
+ if ((code = tf_get_pname(pname)) || (code = tf_get_pinst(pinst))) {
+ tf_close();
+ return code;
+ }
+ /* Ensure ticket is valid. */
+ now = time(NULL);
+ while (tf_get_cred(&cred) == KSUCCESS) {
+ if (strcmp(cred.service, "krbtgt") != 0)
+ continue;
+ cred.issue_date = krb_life_to_time(cred.issue_date, cred.lifetime);
+ if (now - cred.issue_date > 1) {
+ tf_close();
+ return KFAILURE;
+ }
+ }
+ tf_close();
+ if (syslog_flag)
+ syslog(LOG_INFO, "Ticket file %s : %s.%s for %d", tf_name, pname,
+ pinst, auth_data->uid);
+ return KSUCCESS;
+}
+/** Find a valid ticket for the user in /tmp.
+ *
+ * @param tktstring Buffer that will hold the path to the ticket file.
+ * @param auth_data Data about the authentication we're attempting.
+ * @return An error code or #IDENT_AUTH_OKAY.
+ */
+static int
+krb_find_ticket(char *tktstring, struct ident_auth_data *auth_data)
+{
+ int rcode;
+ char temp[MAXPATHLEN];
+ DIR *temp_dir;
+ struct dirent *dp;
+
+ /* Ideally, we want to dive into the kernel and get TKTFILE from the
+ environment of the user's process. Right now, we just cheat and look
+ in typical places. Start by trying the K4 standard. */
+ sprintf(tktstring, "/tmp/tkt%d", auth_data->uid);
+ if (krb_is_ticket(tktstring, auth_data) == KSUCCESS)
+ return IDENT_AUTH_OKAY;
+
+ /* Now we will try grupping through /tmp for a ticket file. */
+ temp_dir = opendir("/tmp");
+ for (dp = readdir(temp_dir); dp != NULL; dp = readdir(temp_dir)) {
+ if (strncmp(dp->d_name, "tkt", strlen("tkt")) != 0)
+ continue;
+ if (strlen(dp->d_name) >= MAXPATHLEN - 6)
+ continue;
+ sprintf(temp, "/tmp/%s", dp->d_name);
+ rcode = krb_is_ticket(temp, auth_data);
+ if (rcode == KSUCCESS ) {
+ strncpy(tktstring, temp, MAXPATHLEN - 1);
+ closedir(temp_dir);
+ return IDENT_AUTH_OKAY;
+ }
+ if (syslog_flag && debug_flag)
+ syslog(LOG_DEBUG, "Rejected %s : %d", dp->d_name, rcode);
+ }
+ closedir(temp_dir);
+ return IDENT_USER_CANT_AUTH;
+}
-/*
- * Start the responder side of an authentication exchange.
+/** Start the responder side of an authentication exchange.
+ *
+ * This function doesn't send any data to the remote system. It just makes
+ * sure that we have a ticket file for the user and obtains the needed service
+ * ticket that we'll use later on.
+ *
+ * @param auth_data Data about the authentication we're attempting.
+ * @return An error code or #IDENT_AUTH_OKAY.
*/
-static int krb_responder_start(auth_data)
- struct ident_auth_data *auth_data ;
+static int
+krb_responder_start(struct ident_auth_data *auth_data)
{
struct hostent *host_name;
char *host;
char instance[INST_SZ];
char realm[REALM_SZ];
- char tktstring[MAXPATHLEN];
+ char tktstring[MAXPATHLEN];
KTEXT_ST authent;
CREDENTIALS cr;
struct krb_state *kstate;
char *p;
- kstate = ( struct krb_state *) malloc(sizeof(struct krb_state)) ;
- if ( kstate == NULL )
- return IDENT_SYSTEM_ERROR ;
- if ( krb_find_ticket(&tktstring,auth_data) != IDENT_AUTH_OKAY ) {
- return IDENT_USER_CANT_AUTH ;
- }
+ kstate = malloc(sizeof(struct krb_state));
+ if (kstate == NULL)
+ return IDENT_SYSTEM_ERROR;
+ if (krb_find_ticket(tktstring, auth_data) != IDENT_AUTH_OKAY)
+ return IDENT_USER_CANT_AUTH;
krb_set_tkt_string(tktstring);
- /* Canonicalize hostname */
- host_name = gethostbyaddr((char *) (auth_data->remote_addr), sizeof(struct in_addr), AF_INET);
- if (!host_name) {
- return IDENT_SYSTEM_ERROR;
- }
+ /* Get the name of the remote host to determine the service ticket. */
+ host_name = gethostbyaddr((char *) auth_data->remote_addr,
+ sizeof(struct in_addr), AF_INET);
+ if (host_name == NULL)
+ return IDENT_SYSTEM_ERROR;
host = strdup(host_name->h_name);
if (host == NULL)
return IDENT_SYSTEM_ERROR;
-
- strncpy(instance, host_name->h_name, sizeof(instance)-1);
- instance[sizeof(instance)-1] = '\0';
+
+ /* Form the name of the service ticket. */
+ strncpy(instance, host_name->h_name, sizeof(instance) - 1);
+ instance[sizeof(instance) - 1] = '\0';
p = strchr(instance, '.');
if (p != NULL)
*p = '\0';
-
- p = instance ;
-
- while ( *p != '\0' ) {
- if ( isupper((int) *p) ) {
- *p = tolower((int) *p) ;
- }
- p++ ;
- }
-
- strncpy(realm, krb_realmofhost(host),(REALM_SZ - 1));
+ for (p = instance; *p != '\0'; p++)
+ if (isupper((int) *p))
+ *p = tolower((int) *p);
+ strncpy(realm, krb_realmofhost(host), REALM_SZ - 1);
free(host);
+ if (syslog_flag && debug_flag)
+ syslog(LOG_DEBUG, "Fetching ticket :%s.%s@%s:",
+ IDENT_AUTH_KRB_SERVICE, instance, realm);
- if (syslog_flag && debug_flag ){
- syslog(LOG_DEBUG,"Fetching ticket :%s.%s@%s:",
- IDENT_AUTH_KRB_SERVICE,instance,realm);
- }
-
- /* Fetch imap.hostname service key */
- (void) krb_mk_req(&authent,IDENT_AUTH_KRB_SERVICE , instance, realm, 0);
+ /* Fetch the service ticket and initialize our state information. */
+ krb_mk_req(&authent, IDENT_AUTH_KRB_SERVICE, instance, realm, 0);
memset(&authent, 0, sizeof(authent));
-
- if (krb_get_cred(IDENT_AUTH_KRB_SERVICE , instance, realm, &cr)) {
- return IDENT_USER_CANT_AUTH;
- }
-
- /* Do we need to know who we are ? */
- /* strcpy(kstate->user, user); */
-
- memset((char *)kstate, 0, sizeof(*kstate));
+ if (krb_get_cred(IDENT_AUTH_KRB_SERVICE, instance, realm, &cr))
+ return IDENT_USER_CANT_AUTH;
+ memset(kstate, 0, sizeof(*kstate));
strcpy(kstate->service, IDENT_AUTH_KRB_SERVICE);
kstate->authstepno = 0;
memcpy(kstate->session, cr.session, sizeof(des_cblock));
des_key_sched(kstate->session, kstate->schedule);
-
-
strcpy(kstate->instance, instance);
strcpy(kstate->realm, realm);
-
memset(&cr, 0, sizeof(cr));
- auth_data->auth_method_data = (void *)kstate;
- return IDENT_AUTH_OKAY ;
+ auth_data->auth_method_data = kstate;
+
+ return IDENT_AUTH_OKAY;
}
-/*
- * Perform responder-side authentication protocol exchange
- * Returns IDENT_AUTH_OKAY if authentication can be complete after
- * sending our responder reply.
+/** Perform responder-side authentication protocol exchange.
+ *
+ * This function talks to the remote system, passing along the required
+ * Kerberos v4 SASL information. It does mutual authentication if needed and
+ * then returns the status of the authentication.
+ *
+ * @param auth_data Data about the authentication we're attempting.
+ * @return An error code or #IDENT_AUTH_OKAY.
*/
-static int krb_responder_auth(auth_data)
-
- struct ident_auth_data *auth_data ;
+static int
+krb_responder_auth(struct ident_auth_data *auth_data)
{
static KTEXT_ST authent;
- struct krb_state *kstate = (struct krb_state *) auth_data->auth_method_data;
+ struct krb_state *kstate = auth_data->auth_method_data;
char tmp[IDENT_BUFFER_SIZE];
- char resp[IDENT_BUFFER_SIZE];
- char output[IDENT_BUFFER_SIZE];
- char *resp_ptr ;
+ char resp[IDENT_BUFFER_SIZE];
+ char output[IDENT_BUFFER_SIZE];
+ char *resp_ptr ;
char line[IDENT_BUFFER_SIZE];
- char *line_ptr ;
- IDENT_INT16 i,j,k,resp_len, len , munch;
- int32_t challenge ;
- struct ident_auth_data auth_reply ;
- int code,rcode;
- int timeout = IDENT_READ_TIMEOUT ;
- struct passwd *paswd_entry ;
-
- while ( kstate->authstepno > -1 ) {
- switch (kstate->authstepno++) {
- case 0:
- /* Get challenge */
- sscanf(auth_data->authenticate_data," KERBEROS_V4 , %[A-Za-z0-9+/=]",tmp ) ;
- rcode = ident_decodebase64(tmp);
-
- /* Requester gave us challenge, respond with ticket+authenticator */
- if (rcode < 4) {
- kstate->authstepno = -1;
- return IDENT_INVALID_REQ_INFO;
- }
-
- kstate->challenge = ntohl(*(int *)tmp);
-
-
- code = krb_mk_req(&authent, kstate->service, kstate->instance,
- kstate->realm, kstate->challenge);
- if (code) {
- kstate->authstepno = -1;
- return IDENT_AUTH_FAIL;
- }
- /* Now we need to formulate the response */
- /* port, port : AUTHENTICATE : KERBEROS_V4, BASE64(htonl(authent.len)athent.dat htonl(identent.len)identent.dat) */
- /* the ident dat looks like
- ** [16bit flag][resp port][req port][authid len][authid][pad]
- ** 16 hton 16 hton 16 hton 16 hton ??? pad to multiple of 8
- ** And then the whole thing is encrypted with the session key
- */
-
- munch = sizeof(IDENT_INT16) ;
-
- /* memcpy(to,from,length ) */
- k = htons(mutual_auth_flag) ;
- resp_ptr = resp ;
- memcpy(resp_ptr,&k,munch) ;
-
-
-
- k = htons(auth_data->local_port) ;
- resp_ptr += munch ;
- memcpy(resp_ptr,&k,munch) ;
-
- k = htons(auth_data->remote_port) ;
- resp_ptr += munch ;
- memcpy(resp_ptr,&k,munch) ;
-
-
- paswd_entry = getpwuid(auth_data->uid);
- i = strlen(paswd_entry->pw_name);
-
- k = htons(i) ;
- resp_ptr += munch ;
- memcpy(resp_ptr,&k,munch) ;
- resp_ptr += munch ;
-
- strcpy(resp_ptr,paswd_entry->pw_name);
-
- k = sizeof(des_cblock) ;
- j = i%k;
- resp_ptr += i ;
-
- /* Pad to a multiple of sizeof(des_cblock) */
- bzero(resp_ptr,k-j) ;
- resp_len = 4*(munch)+i+k-j ;
-
- if ( syslog_flag && debug_flag ) {
- syslog(LOG_DEBUG,"Data: %4.4x:%4.4x:%4.4x:%4.4x:%s",
- htons(mutual_auth_flag) ,
- htons(auth_data->remote_port),
- htons(auth_data->local_port),
- htons(i),
- paswd_entry->pw_name);
- syslog(LOG_DEBUG,"Resp:%d:%4.4x:%4.4x:%4.4x:%4.4x:%s",munch,
- *((IDENT_INT16*) resp),
- *((IDENT_INT16*) &(resp[munch])),
- *((IDENT_INT16*) &(resp[2*munch])),
- *((IDENT_INT16*) &(resp[3*munch])),
- &(resp[4*munch]));
- }
- des_pcbc_encrypt((des_cblock *) resp,(des_cblock *) output, resp_len ,kstate->schedule,&(kstate->session),1 ) ;
-
- resp_ptr = tmp ;
- k = htons(authent.length);
- memcpy(resp,(char*)&k,(munch));
- resp_ptr = &(resp[(munch)]);
- memcpy(resp_ptr,authent.dat,authent.length);
- resp_ptr = &(resp[(munch)+authent.length]);
- k = htons(resp_len);
- memcpy(resp_ptr,(char *)&k,(munch));
- resp_ptr = &(resp[(munch)+authent.length+(munch)]);
- memcpy(resp_ptr,output,resp_len);
- len = munch + authent.length + munch + resp_len ;
-
- ident_writebase64(resp,tmp,len);
- sprintf(line," AUTHENTICATE : %s , %s ",auth_data->auth_struct->auth_method,tmp );
- do_out(line,auth_data);
-
- if (mutual_auth_flag & MUTUAL_AUTH_BIT ) {
- return IDENT_AUTH_OKAY;
- }
- break;
-
- case 1:
- /*
- * Requester gave us mutual auth reply.
- */
- line[0] = '\0' ;
-
- line_ptr = sfgets(line,IDENT_BUFFER_SIZE,auth_data->fp,timeout,auth_data);
- if ( line_ptr == NULL ) {
- do_error(IDENT_NO_MUTUAL_AUTH,auth_data);
- }
- rcode = parse_auth_line(line,&auth_reply);
- if( rcode != IDENT_AUTH_OKAY ) {
- do_error(rcode,&auth_reply) ;
- }
- /* Check if the data is the same */
- if (
- ( auth_reply.local_port != auth_data->local_port ) ||
- ( auth_reply.remote_port != auth_data->remote_port ) ||
- ( strncmp(auth_reply.auth_struct->auth_method ,
- auth_data->auth_struct->auth_method ,
- strlen(auth_data->auth_struct->auth_method)) != 0 ) ) {
-
- if (debug_flag && syslog_flag)
- syslog(LOG_DEBUG, "Auth reply does not match auth_data %d,%d : %d,%d", auth_reply.local_port,auth_reply.remote_port,auth_data->local_port,auth_data->remote_port );
- do_error(IDENT_MUTUAL_AUTH_FAIL,auth_data);
- }
- /* Get challenge */
- sscanf(auth_reply.authenticate_data," KERBEROS_V4 , %[A-Za-z0-9+/=]",tmp ) ;
- rcode = ident_decodebase64(tmp);
-
- if (rcode < 4) {
- kstate->authstepno = -1;
- return IDENT_INVALID_RESP_INFO;
- }
-
- des_ecb_encrypt((des_cblock *)tmp, (des_cblock *)tmp,
- kstate->schedule, 0);
- memcpy(&challenge,tmp,sizeof(challenge)) ;
- challenge = ntohl(challenge);
- if (challenge != kstate->challenge + 1) {
- /* Server failed to mutually authenticte */
- kstate->authstepno = -1;
- if (debug_flag && syslog_flag)
- syslog(LOG_DEBUG, "Challenge failed:%d:%d",kstate->challenge,challenge);
- return IDENT_MUTUAL_AUTH_FAIL;
- }
- if (debug_flag && syslog_flag)
- syslog(LOG_DEBUG, "Challenge succeeded:%d:%d",kstate->challenge,challenge);
-
- return IDENT_AUTH_OKAY;
-
- default:
- kstate->authstepno = -1;
- return IDENT_SYSTEM_ERROR;
- }
- }
- return 1;
-}
-
-
-/*
-** Does trivial (i.e. passwd file based auth)
-**
-*/
-static int trivial_responder_start( auth_data)
-struct ident_auth_data *auth_data;
-{
+ char *line_ptr ;
+ IDENT_INT16 i, j, k, resp_len, len, munch;
+ int32_t challenge;
+ struct ident_auth_data auth_reply;
+ int code, rcode;
+ int timeout = IDENT_READ_TIMEOUT;
+ struct passwd *paswd_entry;
+
+ while (kstate->authstepno > -1) {
+ switch (kstate->authstepno++) {
+ case 0:
+ /* Get challenge. */
+ sscanf(auth_data->authenticate_data,
+ " KERBEROS_V4 , %[A-Za-z0-9+/=]", tmp);
+ rcode = ident_decodebase64(tmp);
+
+ /* Requester gave us challenge, respond with ticket and
+ authenticator. */
+ if (rcode < 4) {
+ kstate->authstepno = -1;
+ return IDENT_INVALID_REQ_INFO;
+ }
+ memcpy(&kstate->challenge, tmp, sizeof(int32_t));
+ kstate->challenge = ntohl(kstate->challenge);
+ code = krb_mk_req(&authent, kstate->service, kstate->instance,
+ kstate->realm, kstate->challenge);
+ if (code != 0) {
+ kstate->authstepno = -1;
+ return IDENT_AUTH_FAIL;
+ }
+
+ /* Now we need to formulate the response. The response should
+ look like the following:
+
+ <port>, <port> : AUTHENTICATE : KERBEROS_V4, <auth> <ident>
+
+ <auth> is the 32-bit length of the authenticator in network
+ byte order prepended to the authenticator and then encoded in
+ base64. <ident> is the 32-bit length of the ident information
+ in network byte order prepended to the ident information and
+ then encoded in base64.
+
+ The ident information looks like:
+
+ [flag][resp port][req port][authid len][authid][pad]
+ <-16-><----16---><---16---><----16----><--??--><-?->
+
+ where padding is added to the end to pad the whole thing to a
+ multiple of eight. The entire thing is then encrypted in the
+ session key from the authenticator. All values above are in
+ network byte order. */
+ munch = sizeof(IDENT_INT16);
+ resp_ptr = resp;
+ k = htons(mutual_auth_flag);
+ memcpy(resp_ptr, &k, munch);
+ resp_ptr += munch;
+ k = htons(auth_data->local_port);
+ memcpy(resp_ptr, &k, munch);
+ resp_ptr += munch;
+ k = htons(auth_data->remote_port);
+ memcpy(resp_ptr, &k, munch);
+ resp_ptr += munch;
+ paswd_entry = getpwuid(auth_data->uid);
+ i = strlen(paswd_entry->pw_name);
+ k = htons(i);
+ memcpy(resp_ptr, &k, munch);
+ resp_ptr += munch;
+ strcpy(resp_ptr, paswd_entry->pw_name);
+ resp_ptr += i;
+ k = sizeof(des_cblock);
+ j = i % k;
+
+ /* Pad to a multiple of sizeof(des_cblock). */
+ memset(resp_ptr, 0, k - j);
+ resp_len = 4 * (munch) + i + k - j;
+
+ /* Log what we're doing for debugging purposes. */
+ if (syslog_flag && debug_flag) {
+ syslog(LOG_DEBUG, "Data: %4.4x:%4.4x:%4.4x:%4.4x:%s",
+ htons(mutual_auth_flag),
+ htons(auth_data->remote_port),
+ htons(auth_data->local_port),
+ htons(i), paswd_entry->pw_name);
+ syslog(LOG_DEBUG, "Resp: %d:%4.4x:%4.4x:%4.4x:%4.4x:%s",
+ munch, *((IDENT_INT16 *) resp),
+ *((IDENT_INT16 *) &(resp[munch])),
+ *((IDENT_INT16 *) &(resp[2 * munch])),
+ *((IDENT_INT16 *) &(resp[3 * munch])),
+ &(resp[4 * munch]));
+ }
+
+ /* Encrypt the ident information. */
+ des_pcbc_encrypt((des_cblock *) resp, (des_cblock *) output,
+ resp_len, kstate->schedule, &kstate->session, 1);
+
+ /* Now, build the authenticator and convert it to base64. */
+ k = htons(authent.length);
+ memcpy(resp, &k, munch);
+ resp_ptr = &resp[munch];
+ memcpy(resp_ptr, authent.dat, authent.length);
+ resp_ptr = &resp[munch + authent.length];
+ k = htons(resp_len);
+ memcpy(resp_ptr, &k, munch);
+ resp_ptr = &resp[munch + authent.length + munch];
+ memcpy(resp_ptr, output, resp_len);
+ len = munch + authent.length + munch + resp_len;
+ ident_writebase64(resp, tmp, len);
+
+ /* Send the output to the remote side. If we're not doing mutual
+ authentication, we're done. */
+ sprintf(line, " AUTHENTICATE : %s , %s ",
+ auth_data->auth_struct->auth_method, tmp);
+ do_out(line, auth_data);
+ if (mutual_auth_flag & MUTUAL_AUTH_BIT)
+ return IDENT_AUTH_OKAY;
+ break;
+
+ case 1:
+ /* Requester gave us mutual auth reply. */
+ line[0] = '\0';
+ line_ptr = sfgets(line, IDENT_BUFFER_SIZE, auth_data->fp,
+ timeout, auth_data);
+ if (line_ptr == NULL)
+ do_error(IDENT_NO_MUTUAL_AUTH, auth_data);
+ rcode = parse_auth_line(line, &auth_reply);
+ if (rcode != IDENT_AUTH_OKAY)
+ do_error(rcode, &auth_reply);
+
+ /* Check if the data is the same */
+ if ( (auth_reply.local_port != auth_data->local_port)
+ || (auth_reply.remote_port != auth_data->remote_port)
+ || (strncmp(auth_reply.auth_struct->auth_method,
+ "KERBEROS_V4", strlen("KERBEROS_V4")) != 0)) {
+ if (debug_flag && syslog_flag)
+ syslog(LOG_DEBUG, "Auth reply does not match auth_data"
+ " %d,%d : %d,%d", auth_reply.local_port,
+ auth_reply.remote_port, auth_data->local_port,
+ auth_data->remote_port);
+ do_error(IDENT_MUTUAL_AUTH_FAIL, auth_data);
+ }
+
+ /* Get challenge */
+ sscanf(auth_reply.authenticate_data,
+ " KERBEROS_V4 , %[A-Za-z0-9+/=]", tmp);
+ rcode = ident_decodebase64(tmp);
+ if (rcode < 4) {
+ kstate->authstepno = -1;
+ return IDENT_INVALID_RESP_INFO;
+ }
+
+ /* Decrypt the challenge and check it. */
+ des_ecb_encrypt((des_cblock *) tmp, (des_cblock *) tmp,
+ kstate->schedule, 0);
+ memcpy(&challenge, tmp, sizeof(challenge));
+ challenge = ntohl(challenge);
+ if (challenge != kstate->challenge + 1) {
+ kstate->authstepno = -1;
+ if (debug_flag && syslog_flag)
+ syslog(LOG_DEBUG, "Challenge failed: %d:%d",
+ kstate->challenge, challenge);
+ return IDENT_MUTUAL_AUTH_FAIL;
+ }
+ if (debug_flag && syslog_flag)
+ syslog(LOG_DEBUG, "Challenge succeeded: %d:%d",
+ kstate->challenge, challenge);
+ return IDENT_AUTH_OKAY;
- struct passwd *paswd_entry ;
- if ( allow_trivial ) {
- paswd_entry = getpwuid(auth_data->uid);
- if (!paswd_entry || auth_data->uid != paswd_entry->pw_uid) {
- do_error(IDENT_NO_USER,auth_data);
- }
- auth_data->auth_method_data = (void *) paswd_entry ;
- return IDENT_AUTH_OKAY ;
- } else {
- do_error(IDENT_INVALID_REQ_INFO,auth_data);
- }
- return 1;
-}
-
-static int trivial_responder_auth( auth_data)
-struct ident_auth_data *auth_data;
-{
- struct passwd *pwd_entry ;
- char tmp[IDENT_BUFFER_SIZE] ;
- if ( allow_trivial) {
- /* Do we want to do noident check here ? */
- pwd_entry = ( struct passwd *) auth_data->auth_method_data;
- if ( ! uidonly_flag ) {
- sprintf(tmp," USERID : UNIX :%s ",
- pwd_entry->pw_name);
- } else {
- sprintf(tmp," USERID : UNIX :%d ",
- auth_data->uid) ;
+ default:
+ kstate->authstepno = -1;
+ return IDENT_SYSTEM_ERROR;
+ }
}
- do_out(tmp,auth_data);
- return IDENT_AUTH_OKAY ;
- } else {
- do_error(IDENT_INVALID_REQ_INFO,auth_data);
- }
- return 1;
-}
-
-
-
-
-
+ return IDENT_AUTH_FAIL;
+}
-static int null_responder_start() {
- return IDENT_AUTH_NOT_SUPPORTED ;
+/** Start traditional ident authentication.
+ *
+ * Does nothing except retrieve the password file entry for the user UID.
+ *
+ * @param auth_data Data about the authentication we're attempting.
+ * @return An error code or #IDENT_AUTH_OKAY.
+ */
+static int
+trivial_responder_start(struct ident_auth_data *auth_data)
+{
+ struct passwd *paswd_entry;
+
+ if (allow_trivial) {
+ paswd_entry = getpwuid(auth_data->uid);
+ if (!paswd_entry || auth_data->uid != paswd_entry->pw_uid)
+ do_error(IDENT_NO_USER, auth_data);
+ auth_data->auth_method_data = paswd_entry;
+ return IDENT_AUTH_OKAY;
+ } else
+ do_error(IDENT_INVALID_REQ_INFO, auth_data);
+ return IDENT_AUTH_FAIL;
}
-static int null_responder_auth() {
+/** Send a traditional ident response.
+ *
+ * Implements traditional ident. Sends either the username or the UID
+ * depending on our flags if trivial authentication is enabled.
+ *
+ * @param auth_data Data about the authentication we're attempting.
+ * @return An error code or #IDENT_AUTH_OKAY.
+ */
+static int
+trivial_responder_auth(struct ident_auth_data *auth_data)
+{
+ struct passwd *pwd_entry;
+ char tmp[IDENT_BUFFER_SIZE];
- return IDENT_AUTH_NOT_SUPPORTED ;
+ /* Do we want to do noident check here? */
+ if (allow_trivial) {
+ pwd_entry = auth_data->auth_method_data;
+ if (uidonly_flag)
+ sprintf(tmp, " USERID : UNIX :%d ", auth_data->uid);
+ else
+ sprintf(tmp, " USERID : UNIX :%s ", pwd_entry->pw_name);
+ do_out(tmp, auth_data);
+ return IDENT_AUTH_OKAY;
+ } else
+ do_error(IDENT_INVALID_REQ_INFO, auth_data);
+ return IDENT_AUTH_FAIL;
}
-static void null_free_state() {
- return ;
-}
+/* Null responder implementations, which always return an error. */
+static int null_responder_start(void) { return IDENT_AUTH_NOT_SUPPORTED; }
+static int null_responder_auth(void) { return IDENT_AUTH_NOT_SUPPORTED; }
+static void null_free_state(void) { return; }
+/** @file
+ * Defines for the Kerberos v4 authentication mechanism.
+ *
+ * The contents of this file mostly match similar things in the sident.h
+ * header file. Some things from there should be moved here, and for the rest
+ * the S/Ident responder code should just include sident.h.
+ *
+ * @author Booker C. Bense <bbense@stanford.edu>
+ *
+ * $Id$
+ */
-#ifndef _IDENT_AUTH_H
-#define _IDENT_AUTH_H
+#ifndef IDENT_AUTH_H
+#define IDENT_AUTH_H 1
+/** Default delay for network reads. */
+#define IDENT_READ_TIMEOUT 60
+
+/** Buffer size sufficient to hold a complete request or response. */
#define IDENT_BUFFER_SIZE 4096
+/** A 16-bit unsigned type. */
#ifndef IDENT_INT16
-#define IDENT_INT16 unsigned short
+# define IDENT_INT16 unsigned short
#endif
-#define MUTUAL_AUTH_BIT 0x01
-
-#ifdef TESTING
-/* For testing , should be "ident" for real */
-#define IDENT_AUTH_KRB_SERVICE "rcmd"
-#else
-#define IDENT_AUTH_KRB_SERVICE "ident"
-#endif
-#define IDENT_READ_TIMEOUT 60
-/* stolen from sendmail */
-#ifndef ARBPTR_T
-# define ARBPTR_T void *
-#endif
+/** Bit to determine if mutual authentication is needed. */
+#define MUTUAL_AUTH_BIT 0x01
-/*
- *
- * Structs for ident authentication
- *
- */
+/** Internal structure storing data about a responder method.
+ *
+ * This struct has the same name but a different definition as a similar
+ * struct in sident.h. In both cases, they're internal and really shouldn't
+ * be included in the public header file at all. This part needs some work.
+ */
struct ident_responder_auth {
- char *auth_method; /* Name of authentication mechanism */
- int (*start)(); /* Start a responder->requester authentication */
- int (*auth)(); /* Do an authentication protocol exchange */
- void (*free_state)(); /* Free an authentication state */
+ char *auth_method; /**< Name of authentication mechanism. */
+
+ /** Start a responder->requester authentication. */
+ char *(*start)(struct ident_auth_client_data *);
+
+ /** Do an authentication protocol exchange. */
+ int (*auth)(struct ident_auth_client_data *);
+
+ /** Free an authentication state structure. */
+ void (*free_state)(void *);
};
+/** Internal structure containing responder information. */
struct ident_auth_data {
- FILE *fp ; /* input stream */
- char *port_data ; /* points to port data part of auth_line */
- char *cmd_data ; /* points to "cmd" (i.e. AUTHENTICATE) part of line */
- char *authenticate_data ; /* points to AUTHENTICATE part of line */
- int uid; /* Uid of process */
- int pid; /* Pid of process */
- struct ident_responder_auth *auth_struct ; /* Pointer to auth_methods */
- int local_port ; /* Local port of connection */
- int remote_port ; /* Remote port of connection */
-
- struct in_addr *local_addr ; /* IP address local */
- struct in_addr *remote_addr ; /* IP address remote */
- ARBPTR_T auth_method_data ; /* Ptr to arbitrary struct needed for auth _method */
+ FILE *fp; /**< Input stream. */
+ char *port_data; /**< Points to port data part of auth_line. */
+ char *cmd_data; /**< Points to command part of line. */
+ char *authenticate_data; /**< Points to AUTHENTICATE part of line. */
+ int uid; /**< UID of process. */
+ int pid; /**< PID of process. */
-};
+ /** Pointer to authentication methods. */
+ struct ident_responder_auth *auth_struct;
+ int local_port; /**< Local port of connection. */
+ int remote_port; /**< Remote port of connection. */
-#endif
+ /** Local IP address. */
+ struct in_addr *local_addr;
+
+ /** Remote IP address. */
+ struct in_addr *remote_addr;
+
+ /** Pointer to method-specific data used for authentication. */
+ void *auth_method_data;
+};
+
+#endif /* !IDENT_AUTH_H */
* $Id$
*/
-#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
-#include <grp.h>
#include <netdb.h>
-#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/file.h>
-#include <sys/ioctl.h>
-#include <sys/param.h>
#include <sys/socket.h>
-#include <sys/time.h>
#include <sys/types.h>
-#include <sys/wait.h>
+#include <syslog.h>
#include <unistd.h>
/* BSDI needs <netinet/in.h> before <arpa/inet.h>. */
# include <sys/select.h>
#endif
-#include "error.h"
#include "identd.h"
-#include "paths.h"
int verbose_flag = 0;
int debug_flag = 0;
int syslog_flag = 0;
-int multi_flag = 0;
int unknown_flag = 0;
-int uidonly_flag = 0 ;
-int users_can_nosident = ( 0 == 0 ) ;
-int allow_trivial = 0 ;
-int mutual_auth_flag = 0 ;
-int client_only_flag = 0 ;
-
-int lport = 0;
-int fport = 0;
-
-static int syslog_facility = LOG_DAEMON;
-
-/*
-** The structure passing convention for GCC is incompatible with
-** Suns own C compiler, so we define our own inet_ntoa() function.
-** (This should only affect GCC version 1 I think, a well, this works
-** for version 2 also so why bother.. :-)
-*/
-#if defined(__GNUC__) && defined(__sparc__) && !defined(NeXT)
-
-#ifdef inet_ntoa
-#undef inet_ntoa
-#endif
-
-char *inet_ntoa(ad)
- struct in_addr ad;
-{
- unsigned long int s_ad;
- int a, b, c, d;
- static char addr[20];
-
- s_ad = ad.s_addr;
- d = s_ad % 256;
- s_ad /= 256;
- c = s_ad % 256;
- s_ad /= 256;
- b = s_ad % 256;
- a = s_ad / 256;
- sprintf(addr, "%d.%d.%d.%d", a, b, c, d);
-
- return addr;
-}
-#endif
-
-static int comparemem(p1, p2, len)
- unsigned char *p1;
- unsigned char *p2;
- int len;
-{
- int c;
-
- while (len-- > 0)
- if ((c = (int) *p1++ - (int) *p2++) != 0)
- return c;
-
- return 0;
-}
-
-/*
-** Return the name of the connecting host, or the IP number as a string.
-*/
-char *gethost(addr)
- struct in_addr *addr;
+int uidonly_flag = 0;
+int users_can_nosident = 1;
+int allow_trivial = 0;
+int mutual_auth_flag = 0;
+int client_only_flag = 0;
+
+/* Return the name of the connecting host, or the IP number as a string. */
+char *
+gethost(struct in_addr *addr)
{
int i;
struct hostent *hp;
char *hostname;
-
- hp = gethostbyaddr((char *) addr, sizeof(struct in_addr), AF_INET);
- if (hp)
- {
- /* Found a IP -> Name match, now try the reverse for security reasons */
+
+ /* Make sure that forward and reverse DNS match to use a hostname. */
+ hp = gethostbyaddr((char *) addr, sizeof(*addr), AF_INET);
+ if (hp != NULL) {
hostname = strdup(hp->h_name);
if (hostname == NULL)
return inet_ntoa(*addr);
- hp = gethostbyname(hostname);
+ hp = gethostbyname(hostname);
free(hostname);
- if (hp)
- for (i = 0; hp->h_addr_list[i]; i++)
- if (comparemem(hp->h_addr_list[i],
- (unsigned char *) addr,
- sizeof(struct in_addr)) == 0)
- return hp->h_name;
- }
-
- return inet_ntoa(*addr);
-}
-
-
-char *clearmem(bp, len)
- char *bp;
- int len;
-{
- char *cp;
-
- cp = bp;
- while (len-- > 0)
- *cp++ = 0;
-
- return bp;
+ if (hp != NULL)
+ for (i = 0; hp->h_addr_list[i]; i++)
+ if (memcmp(hp->h_addr_list[i], addr, sizeof(*addr)) == 0)
+ return hp->h_name;
+ }
+ return inet_ntoa(*addr);
}
-
-/*
-** Main entry point into this daemon
-*/
-int main(argc,argv)
- int argc;
- char *argv[];
+/* Main entry point into this daemon. */
+int
+main(int argc, char *argv[])
{
- int i, len;
+ int len;
struct sockaddr_in sin;
struct in_addr laddr, faddr;
-
- int opt_count = 0; /* Count of option flags */
-
-
- /*
- ** Parse the command line arguments
- */
- for (i = 1; i < argc && argv[i][0] == '-'; i++) {
- opt_count++;
- switch (argv[i][1])
- {
- case 'l': /* Use the Syslog daemon for logging */
- syslog_flag++;
- break;
-
- case 'n':
+ int option;
+
+ /* Parse options. */
+ opterr = 0;
+ while ((option = getopt(argc, argv, "CdeMNnlTVv")) != EOF) {
+ switch (option) {
+ case 'C':
+ client_only_flag++;
+ break;
+ case 'd':
+ debug_flag++;
+ break;
+ case 'e':
+ unknown_flag = 1;
+ break;
+ case 'l':
+ syslog_flag++;
+ break;
+ case 'M':
+ mutual_auth_flag++;
+ break;
+ case 'N':
+ users_can_nosident = 0;
+ break;
+ case 'n':
uidonly_flag = 1;
break;
-
- case 'e':
- unknown_flag = 1;
- break;
-
- case 'V': /* Give version of this daemon */
- printf("[%s]\r\n", PACKAGE_STRING);
- exit(0);
- break;
-
- case 'v': /* Be verbose */
- verbose_flag++;
- break;
-
- case 'd': /* Enable debugging */
- debug_flag++;
- break;
-
- case 'N': /* Disable users ".nosident" files */
- users_can_nosident = ( 0 == 1 ) ;
- break;
- case 'M': /* Turn off mutual auth */
- mutual_auth_flag++ ;
- break ;
-
- case 'T': /* Allow trivial auth */
- allow_trivial++ ;
- break;
- case 'C': /* Turn on client only port checking */
- client_only_flag++ ;
- break;
-
- default:
- ERROR1("Bad option %s", argv[i]);
- break;
- }
+ case 'T':
+ allow_trivial++ ;
+ break;
+ case 'v':
+ verbose_flag++;
+ break;
+ case 'V':
+ printf("%s\n", PACKAGE_STRING);
+ exit(0);
+ break;
+ default:
+ fprintf(stderr, "sidentd: bad option -%c\n", optopt);
+ exit(1);
+ break;
+ }
+ }
+ argc -= optind;
+ if (argc > 0) {
+ fprintf(stderr, "sidentd: too many arguments\n");
+ exit(1);
}
- if (i < argc)
- ERROR1("Too many arguments: ignored from %s", argv[i]);
-
-
- /*
- ** We used to call k_open here. But then the file descriptor
- ** kd->fd open on /dev/kmem is shared by all child processes.
- ** From the fork(2) man page:
- **
- ** o The child process has its own copy of the parent's descriptors.
- ** These descriptors reference the same underlying objects. For
- ** instance, file pointers in file objects are shared between the
- ** child and the parent so that an lseek(2) on a descriptor in the
- ** child process can affect a subsequent read(2) or write(2) by
- ** the parent.
- **
- ** Thus with concurrent (simultaneous) identd client processes,
- ** they step on each other's toes when they use kvm_read.
- **
- ** Calling k_open here was a mistake for another reason too: we
- ** did not yet honor -u and -g options. Presumably we are
- ** running as root (unless the in.identd file is setuid), and
- ** then we can open kmem regardless of -u and -g values.
- **
- **
- ** Open the kernel memory device and read the nlist table
- **
- ** if (k_open() < 0)
- ** ERROR("main: k_open");
- */
-
- /*
- ** Get foreign internet address
- */
+ /* Get the remote Internet address. If this fails, a user has tried to
+ start us from the command line or the network link died; either way,
+ the message won't reach the other end. */
len = sizeof(sin);
- if (getpeername(0, (struct sockaddr *) &sin, &len) == -1)
- {
- /*
- ** A user has tried to start us from the command line or
- ** the network link died, in which case this message won't
- ** reach to other end anyway, so lets give the poor user some
- ** errors.
- */
- perror("in.sidentd: getpeername()");
- exit(1);
+ if (getpeername(0, (struct sockaddr *) &sin, &len) < 0) {
+ fprintf(stderr, "sidentd: getpeername failed: %s", strerror(errno));
+ exit(1);
}
-
faddr = sin.sin_addr;
-
-
- /*
- ** Open the connection to the Syslog daemon if requested
- */
+
+ /* If we're logging, open the connection to the syslog daemon. */
if (syslog_flag)
- {
- openlog("sidentd", LOG_PID, syslog_facility);
- }
-
+ openlog("sidentd", LOG_PID, LOG_DAEMON);
- /*
- ** Get local internet address
- */
+ /* Get the local Internet address. If this fails, exit, since we have to
+ have it to check requests. */
len = sizeof(sin);
- if (getsockname(0, (struct sockaddr *) &sin, &len) == -1)
- {
- /*
- ** We can just die here, because if this fails then the
- ** network has died and we haven't got anyone to return
- ** errors to.
- */
- exit(1);
+ if (getsockname(0, (struct sockaddr *) &sin, &len) == -1) {
+ fprintf(stderr, "sidentd: getsockname failed: %s", strerror(errno));
+ exit(1);
}
laddr = sin.sin_addr;
-
- /*
- ** Get the local/foreign port pair from the luser
- */
+ /* Parse the ident request. */
parse(stdin, &laddr, &faddr);
-
- /* Note : we should never return from parse */
exit(0);
}
*/
#ifndef IDENTD_H
-#define IDENTD_H
+#define IDENTD_H 1
-extern char version[];
+#include <stdio.h> /* FILE */
+
+#include "config.h"
+#include "sident.h"
extern int verbose_flag;
extern int debug_flag;
extern int syslog_flag;
-extern int multi_flag;
extern int unknown_flag;
extern int uidonly_flag;
extern int users_can_nosident;
-extern int crypto_flag;
extern int allow_trivial;
extern int mutual_auth_flag;
extern int client_only_flag;
-extern int lport;
-extern int fport;
-
-extern char *gethost();
-
-extern int k_open();
-extern int k_getuid();
-extern int parse();
-extern int parse_config();
-
-#include "sident.h"
-
-#define MAX_PORT 65535
-#define VALID_PORT( _port_ ) ((_port_) > 1 && (_port_) < MAX_PORT )
-
-/* You may want to change this for whatever makes sense at your site. */
-
-#define SERVER_PORT( _port_) ((_port_) < 1024 && (_port_) != 6000 )
-
-#include "config.h"
-
-/* lstat defines */
+extern char *gethost(struct in_addr *);
+extern int parse(FILE *, struct in_addr *laddr, struct in_addr *faddr);
-#ifndef S_IRUSR
-#define S_IRUSR 0000400
-#endif
-#ifndef S_IRGRP
-#define S_IRGRP 0000040
-#endif
-#ifndef S_IWGRP
-#define S_IWGRP 0000020
-#endif
-#ifndef S_IROTH
-#define S_IROTH 0000004
-#endif
-#ifndef S_IWOTH
-#define S_IWOTH 0000002
-#endif
+/* Port checking. You may want to adjust SERVER_PORT for whatever makes sense
+ at your site, in order to exclude other known server ports. Note that
+ these macros evaluate the port number multiple times. */
+#define MAX_PORT 65535
+#define VALID_PORT(p) ((p) > 1 && (p) < MAX_PORT)
+#define SERVER_PORT(p) ((p) < 1024 || (p) == 6000)
#endif /* !IDENTD_H */
* It takes on stdin the output from "netstat -f inet -n | grep ESTAB" in
* either Solaris 2.x (non-standard formats can easily be converted to this)
*
- * laddr.lport faddr.fport .....
+ * laddr.lport faddr.fport .....
*
* or BSD 4.x (the defacto standard netstat output):
*
- * tcp <num> <num> laddr.lport faddr.fport
+ * tcp <num> <num> laddr.lport faddr.fport
*
- * format.
+ * format. Optionally, the delimiter between the address and the port may be
+ * a colon instead.
*
* The output must be numeric, as non-numeric output is truncated when
* hostnames get too long and ambiguous. And we don't want netstat to first
* convert numbers to names and then this program to convert names back to
* numbers.
*
- * @author Casper Dik (casper@fwi.uva.nl)
+ * @author Casper Dik <casper@fwi.uva.nl>
*
* $Id$
*/
-#include <ctype.h>
+#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
-#include <sys/time.h>
#include <sys/types.h>
-#include <pwd.h>
+#include <syslog.h>
/* BSDI needs <netinet/in.h> before <arpa/inet.h>. */
#include <netinet/in.h>
#include <arpa/inet.h>
#include "identd.h"
-#include "error.h"
#include "pidentd.h"
-#include "sident.h"
-
-static int syslog_facility = LOG_DAEMON;
-
-/*
- * To resolve external references that are usually resolved
- * from identd.c
- */
-char *path_unix = NULL;
-char *path_kmem = NULL;
-int lport = 0;
-int fport = 0;
+/* External references that are usually resolved from identd.c. */
int debug_flag = 1;
int syslog_flag = 1;
int
-main()
+main(void)
{
char buf[500];
+ void *ka_ptr;
+ struct kernel *kinfo_ptr;
- void *ka_ptr ;
- struct kernel *kinfo_ptr ;
-
-
- /*
- ** Open the connection to the Syslog daemon if requested
- */
- if (syslog_flag)
- {
- openlog("identd_test", LOG_PID, syslog_facility);
- }
-
+ /* Some things just always syslog, so try to at least put a reasonable
+ program name on them. This needs to be fixed. */
+ openlog("itest", LOG_PID, LOG_DAEMON);
+ /* Open the kernel. */
if (ka_open(&ka_ptr) != 0) {
- fprintf(stderr,"ka_open failed\n");
- exit(1);
+ fprintf(stderr, "ka_open failed\n");
+ exit(1);
}
- while (fgets(buf,sizeof(buf),stdin)) {
- char *loc, *rem, *tmp;
- unsigned short lport, fport;
- struct in_addr faddr, laddr;
- int uid;
- int pid;
- char *cmd, *cmd_and_args;
-
- struct passwd *pwd;
- char buf2[sizeof(buf)];
-
- strcpy(buf2,buf);
-
- loc = strtok(buf, " \t");
- if (strcmp(loc,"tcp") == 0) {
- int i;
- for (i = 0; i < 3; i++)
- loc = strtok(NULL, " \t");
- }
- rem = strtok(NULL, " \t");
- if (loc == NULL || rem == NULL) {
- fprintf(stderr,"Malformed line: %s\n", buf2);
- continue;
- }
- /* parse remote, local address */
- tmp = strrchr(loc,'.');
- if (tmp == NULL) {
- fprintf(stderr,"Malformed line: %s\n", buf2);
- continue;
- }
- *tmp++ ='\0';
- laddr.s_addr = inet_addr(loc);
- lport = atoi(tmp);
-
- tmp = strrchr(rem,'.');
- if (tmp == NULL) {
- fprintf(stderr,"Malformed line: %s\n", buf2);
- continue;
- }
- *tmp++ ='\0';
- fport = atoi(tmp);
- faddr.s_addr = inet_addr(rem);
-
- uid = -1;
-
- pid = 0;
- cmd = "unknown";
- cmd_and_args = "unknown";
-
- /* convert this to ka_lookup */
-
-/* if (k_getuid(&faddr, htons(fport), &laddr, htons(lport), &uid */
-
-/* , &pid */
-/* , &cmd */
-/* , &cmd_and_args */
-
-/* ) != 0) { */
-/* fprintf(stderr,"*unknown*\t%s\t%d\t\t%s\t%d\n", loc, lport, rem, fport); */
-/* continue; */
-/* } */
-
-
- /* Fill up kernel info struct */
-
- /* struct kernel */
- /* { */
- /* Request parameters */
- /* struct sockaddr_in local; */
- /* struct sockaddr_in remote; */
-
- /* Result parameters */
- /* avail_t av; */
-
- /* int status; */
- /* uid_t euid; */
- /* uid_t ruid; */
-
- /* pid_t pid; */
- /* char *cmd; */
- /* char *argv; */
- /* }; */
-
- kinfo_ptr = kernel_alloc() ;
-
-
- kinfo_ptr->local.sin_port = htons(lport) ;
- kinfo_ptr->remote.sin_port = htons(fport) ;
- memcpy(&(kinfo_ptr->local.sin_addr),&laddr,sizeof(struct in_addr));
- memcpy(&(kinfo_ptr->remote.sin_addr),&faddr,sizeof(struct in_addr));
- kinfo_ptr->local.sin_family = AF_INET ;
- kinfo_ptr->remote.sin_family = AF_INET ;
- /* k_getuid returns 0 on success, any non-zero on failure. */
-
-
- if ( ka_lookup(ka_ptr,kinfo_ptr) < 0){
- fprintf(stderr,"ka_lookup failed\n");
- exit(1);
+ /* For each input string, parse it and then look it up in the kernel. */
+ while (fgets(buf, sizeof(buf), stdin) != NULL) {
+ char *loc, *rem, *tmp;
+ unsigned short lport, fport;
+ struct in_addr faddr, laddr;
+ int i;
+ struct passwd *pwd;
+ char buf2[sizeof(buf)];
+ uid_t uid;
+
+ strcpy(buf2, buf);
+
+ loc = strtok(buf, " \t");
+ if (strcmp(loc, "tcp") == 0)
+ for (i = 0; i < 3; i++)
+ loc = strtok(NULL, " \t");
+ rem = strtok(NULL, " \t");
+ if (loc == NULL || rem == NULL) {
+ fprintf(stderr,"Malformed line: %s\n", buf2);
+ continue;
+ }
+
+ /* Parse remote, local address. */
+ tmp = strrchr(loc, ':');
+ if (tmp == NULL)
+ tmp = strrchr(loc, '.');
+ if (tmp == NULL) {
+ fprintf(stderr,"Malformed line: %s\n", buf2);
+ continue;
+ }
+ *tmp++ = '\0';
+ laddr.s_addr = inet_addr(loc);
+ lport = atoi(tmp);
+ tmp = strrchr(rem, ':');
+ if (tmp == NULL)
+ tmp = strrchr(loc, '.');
+ if (tmp == NULL) {
+ fprintf(stderr,"Malformed line: %s\n", buf2);
+ continue;
+ }
+ *tmp++ = '\0';
+ fport = atoi(tmp);
+ faddr.s_addr = inet_addr(rem);
+
+ /* Flesh out the kernel lookup request. */
+ kinfo_ptr = kernel_alloc();
+ kinfo_ptr->local.sin_port = htons(lport);
+ kinfo_ptr->remote.sin_port = htons(fport);
+ memcpy(&kinfo_ptr->local.sin_addr, &laddr, sizeof(struct in_addr));
+ memcpy(&kinfo_ptr->remote.sin_addr, &faddr, sizeof(struct in_addr));
+ kinfo_ptr->local.sin_family = AF_INET;
+ kinfo_ptr->remote.sin_family = AF_INET;
+
+ /* Do the kernel lookup. */
+ if (ka_lookup(ka_ptr, kinfo_ptr) < 0) {
+ fprintf(stderr, "ka_lookup failed\n");
+ exit(1);
+ }
+ if (kinfo_ptr->status == 0) {
+ fprintf(stderr, "Connection not found\n");
+ continue;
+ }
+
+ /* Print out the results. */
+ uid = (kinfo_ptr->ruid == NO_UID) ? kinfo_ptr->euid : kinfo_ptr->ruid;
+ pwd = getpwuid(uid);
+ if (pwd != NULL)
+ printf("%-8.8s", pwd->pw_name);
+ else
+ printf("%-8.8d", kinfo_ptr->ruid);
+ printf(" \t%-13s\t%-4d\t%-13s\t%-4d\tPID=%d\tCMD=%s\tCMD+ARG=%s\n",
+ loc, lport, rem, fport, kinfo_ptr->pid, kinfo_ptr->cmd,
+ kinfo_ptr->argv);
}
-
-
-
- pwd = getpwuid(kinfo_ptr->ruid);
- if (pwd)
- printf("%-8.8s", pwd->pw_name);
- else
- printf("%-8.8d", kinfo_ptr->ruid);
-
- printf (" \t%-13s\t%-4d\t%-13s\t%-4d\tPID=%d\tCMD=%s\tCMD+ARG=%s\n", loc, lport, rem, fport, kinfo_ptr->pid, kinfo_ptr->cmd, kinfo_ptr->argv);
-
- }
-
return 0;
}
+++ /dev/null
-/*
-** kvm.h Header file for the kernel virtual memory access
-** routines
-**
-** This code is in the public domain and may be used freely by anyone
-** who wants to.
-**
-** Last update: 19 Oct 1992
-**
-** Author: Peter Eriksson <pen@lysator.liu.se>
-*/
-
-#ifndef __KVM_H__
-#define __KVM_H__
-
-typedef struct
-{
- int fd;
- char *namelist;
-#ifdef BSD43
- int swap_fd;
- int mem_fd;
-
- int procidx;
- int nproc;
- struct pte *Usrptma;
- struct pte *usrpt;
- struct proc *proctab;
-#endif
-} kvm_t;
-
-
-extern kvm_t *kvm_open();
-extern int kvm_close();
-extern int kvm_nlist();
-extern int kvm_read();
-
-#ifdef BSD43
-extern struct user *kvm_getu();
-extern struct proc *kvm_getproc();
-extern struct proc *kvm_nextproc();
-extern int kvm_setproc();
-#endif
-
-#endif
* This file provides the glue routines needed to use pidentd 3.0.* k_files
* with the S/Ident responder code.
*
+ * Most of the s_* functions are covered by the following license:
+ *
+ * Copyright (c) 1997-1999 Peter Eriksson <pen@lysator.liu.se>
+ *
+ * This program is free software; you can redistribute it and/or modify it as
+ * you wish - as long as you don't claim that you wrote it.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
* @author Booker C. Bense <bbense@stanford.edu>
+ * @author Peter Eriksson <pen@lysator.liu.se>
*
* $Id$
*/
-#include "config.h"
+#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <syslog.h>
#include <unistd.h>
-#ifndef KERNEL_HELPER
-# define KERNEL_HELPER
-#endif
-
-#include "pidentd.h"
-
-
-/* osinfo_get is never actually used, since we don't use the
-** ka_init function in the k_files. Its just to make the
-** compiler happy.
-*/
-
-char *osinfo_build = "the current os" ;
-
-char *
-osinfo_get( char *os_current) {
-
- return NULL ;
+#include "identd.h"
+#include "pidentd.h"
-}
+/* Dummy variables that aren't used but that various kernel modules expect. */
+const char *osinfo_build = "the current os";
+int kernel_threads = 0;
+int kernel_buffers = 0;
+int kernel_attempts = 0;
+/* osinfo_get is never actually used, since we don't use the ka_init function
+ in the k_files. Its just to make the compiler happy. */
+char *osinfo_get(char *os_current) { return NULL; }
+/* Allocate the kernel struct that's used as an interface. */
struct kernel *
kernel_alloc(void)
{
struct kernel *kp;
-
- kp = (struct kernel *) s_malloc(sizeof(struct kernel));
-
-
+ kp = s_malloc(sizeof(struct kernel));
kp->status = -1;
kp->euid = NO_UID;
kp->ruid = NO_UID;
-
kp->pid = NO_PID;
kp->cmd = NULL;
kp->argv = NULL;
-
return kp;
}
-
+/* Free the kernel struct. */
void
kernel_free(struct kernel *kp)
{
s_free(kp->cmd);
s_free(kp->argv);
-
- s_free( kp);
+ s_free(kp);
}
+/* The following functions are all copies or substitutes for the s_* functions
+ provided in pidentd, since they are used by the kernel modules. */
+/* abort replacement. */
+void s_abort(void) { abort(); }
-/*
-** safeio.c - Signal/Async safe wrapper functions
-**
-** Copyright (c) 1997-1999 Peter Eriksson <pen@lysator.liu.se>
-**
-** This program is free software; you can redistribute it and/or
-** modify it as you wish - as long as you don't claim that you wrote
-** it.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-*/
-
-extern int debug_flag ;
-
-void
-s_abort(void)
-{
-
- abort();
-}
-
-/*
-** A "safe" malloc, that always succeeds (or logs an
-** error to syslog and the abort()'s.
-**
-** The buffer returned is zeroed out.
-*/
+/* Safe malloc replacement that always succeeds (if it doesn't, it logs an
+ error message to syslog and then aborts. The buffer is zeroed out before
+ it's returned, similar to calloc. */
void *
s_malloc(size_t size)
{
void *p;
- p = (void *) malloc(size);
- if (p == NULL)
- {
- if (debug_flag)
- fprintf(stderr, "s_malloc(%lu) failed - aborting\n",
- (unsigned long) size);
-
- syslog(LOG_ERR, "malloc(%lu): %m", (unsigned long) size);
- s_abort();
+ p = malloc(size);
+ if (p == NULL) {
+ if (debug_flag)
+ fprintf(stderr, "s_malloc(%lu) failed - aborting\n",
+ (unsigned long) size);
+ syslog(LOG_ERR, "malloc(%lu): %m", (unsigned long) size);
+ s_abort();
}
-
memset(p, 0, size);
return p;
}
-
+/* Safe free replacement that doesn't call the system free if the pointer is
+ NULL (some system free implementations can't handle that). */
void
s_free(void *p)
{
if (p != NULL)
- free(p);
+ free(p);
}
-
+/* Safe strdup replacement. */
char *
s_strdup(const char *s)
{
char *ns;
size_t len;
-
-
+
if (s == NULL)
- return NULL;
-
- len = strlen(s)+1;
- ns = (char *) malloc(len);
- if (ns == NULL)
- {
- syslog(LOG_ERR, "strdup(): malloc(%lu): %m", (unsigned long) len);
- s_abort();
+ return NULL;
+ len = strlen(s) + 1;
+ ns = malloc(len);
+ if (ns == NULL) {
+ syslog(LOG_ERR, "strdup(): malloc(%lu): %m", (unsigned long) len);
+ s_abort();
}
-
memcpy(ns, s, len);
return ns;
}
+#ifndef ENOSR
+# define ENOSR ENFILE
+#endif
+
+/* Safe s_open replacement that repeats the call to open on EINTR and logs a
+ warning on errors that indicate too many open files. */
int
-s_open(const char *path,
- int oflag,
- ...)
+s_open(const char *path, int oflag, ...)
{
int s;
mode_t mode = 0;
- if (oflag & O_CREAT)
- {
- va_list ap;
+ if (oflag & O_CREAT) {
+ va_list ap;
- va_start(ap, oflag);
- /* FIXME: need to use widened form of mode_t here. */
- mode = va_arg(ap, int);
- va_end(ap);
+ va_start(ap, oflag);
+ /* FIXME: need to use widened form of mode_t here. */
+ mode = va_arg(ap, int);
+ va_end(ap);
}
- while ((s = open(path, oflag, mode)) < 0 && errno == EINTR)
- ;
-
- if (s < 0 && (errno == EMFILE
- || errno == ENFILE
- || errno == ENOMEM
-#ifdef ENOSR
- || errno == ENOSR
-#endif
- ))
- {
- /* Too many open files */
-
- syslog(LOG_WARNING, "s_open(\"%s\", 0%o): %m", path, oflag);
- }
-
+ do {
+ s = open(path, oflag, mode);
+ } while (s < 0 && errno == EINTR);
+
+ /* Check for too many open files. */
+ if (s < 0 && (errno == EMFILE || errno == ENFILE || errno == ENOMEM
+ || errno == ENOSR))
+ syslog(LOG_WARNING, "s_open(\"%s\", 0%o): %m", path, oflag);
return s;
}
-
-
-
+/* snprintf replacement that uses vsprintf if vsnprintf isn't available and
+ tries to detect a buffer overrun. This can be replaced with a call to
+ vsnprintf once we have an snprintf replacement. */
int
-s_snprintf(char *buf,
- size_t bufsize,
- const char *format,
- ...)
+s_snprintf(char *buf, size_t bufsize, const char *format, ...)
{
va_list ap;
int retcode;
+ if (bufsize < 1) {
+ syslog(LOG_ERR, "s_snprintf(..., %lu, ...): illegal bufsize",
+ (unsigned long) bufsize);
+ s_abort();
+ }
va_start(ap, format);
-
- if (bufsize < 1)
- {
- syslog(LOG_ERR, "s_snprintf(..., %d, ...): illegal bufsize",
- bufsize);
- s_abort();
- }
-
- buf[bufsize-1] = '\0';
+ buf[bufsize - 1] = '\0';
#ifdef HAVE_VSNPRINTF
retcode = vsnprintf(buf, bufsize, format, ap);
#else
retcode = vsprintf(buf, format, ap);
#endif
-
- if (retcode > 0 && (buf[bufsize-1] != '\0' ||
- retcode > bufsize-1))
- {
- syslog(LOG_ERR, "s_snprintf(..., %d, ...) = %d: buffer overrun\n",
- bufsize, retcode);
-
- s_abort();
+ if (retcode > 0 && (buf[bufsize - 1] != '\0' || retcode > bufsize - 1)) {
+ syslog(LOG_ERR, "s_snprintf(..., %lu, ...) = %d: buffer overrun\n",
+ (unsigned long) bufsize, retcode);
+ s_abort();
}
-
va_end(ap);
-
return retcode;
}
+++ /dev/null
-/** @file
- * A set of functions for emulating kvm on operating systems without them.
- *
- * This code is in the public domain and may be used freely by anyone
- * who wants to.
- *
- * @date 1992-12-12
- * @author Peter Eriksson <pen@lysator.liu.se>
- *
- * $Id$
- */
-
-#include "config.h"
-
-#ifndef NO_KVM
-#ifndef HAVE_LIBKVM
-
-#include <errno.h>
-#include <nlist.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef IRIX
-# include <sys/sbd.h>
-# ifdef IRIX6
-# define K0_TO_PHYS(x) (x)
-# define nlist nlist64
-# endif
-#endif
-
-#ifdef BSD43
-# include <sys/types.h>
-# include <sys/dir.h>
-# include <sys/param.h>
-# include <sys/vmmac.h>
-# include <sys/user.h>
-# ifdef DIRBLKSIZ
-# undef DIRBLKSIZ
-# endif
-# include <sys/proc.h>
-# include <machine/pte.h>
-# include "paths.h"
-#endif
-
-#include "kernel/kvm.h"
-#include "paths.h"
-
-kvm_t *kvm_open(namelist, corefile, swapfile, flag, errstr)
- char *namelist;
- char *corefile;
- char *swapfile;
- int flag;
- char *errstr;
-{
- kvm_t *kd;
-
- if (!namelist)
- namelist = _PATH_UNIX;
- if (!corefile)
- corefile = _PATH_KMEM;
-
-#ifdef BSD43
- if (!swapfile)
- swapfile = _PATH_SWAP;
-#endif
-
- kd = (kvm_t *) malloc(sizeof(kvm_t));
- if (!kd)
- {
- if (errstr)
- perror(errstr);
- return NULL;
- }
-
- kd->namelist = (char *) malloc(strlen(namelist)+1);
- if (!kd->namelist)
- {
- if (errstr)
- perror(errstr);
- return NULL;
- }
-
- if ((kd->fd = open(corefile, flag)) < 0)
- {
- if (errstr)
- perror(errstr);
- free(kd->namelist);
- free(kd);
- return NULL;
- }
-
-#ifdef BSD43
- if ((kd->swap_fd = open(swapfile, flag)) < 0)
- {
- if (errstr)
- perror(errstr);
- close(kd->fd);
- free(kd->namelist);
- free(kd);
- return NULL;
- }
-
- if ((kd->mem_fd = open(_PATH_MEM, flag)) < 0)
- {
- if (errstr)
- perror(errstr);
- close(kd->swap_fd);
- close(kd->fd);
- free(kd->namelist);
- free(kd);
- return NULL;
- }
-#endif
-
- strcpy(kd->namelist, namelist);
- return kd;
-}
-
-
-int kvm_close(kd)
- kvm_t *kd;
-{
- int code;
-
- code = close(kd->fd);
-#ifdef BSD43
- close(kd->swap_fd);
- close(kd->mem_fd);
- if (kd->proctab)
- free(kd->proctab);
-#endif
- free(kd->namelist);
- free(kd);
-
- return code;
-}
-
-
-/*
-** Extract offsets to the symbols in the 'nl' list. Returns 0 if all found,
-** or else the number of variables that was not found.
-*/
-int kvm_nlist(kd, nl)
- kvm_t *kd;
- struct nlist *nl;
-{
- int code;
- int i;
-
-#ifdef IRIX6
- code = nlist64(kd->namelist, nl);
-#else
- code = nlist(kd->namelist, nl);
-#endif
- if (code != 0)
- return code;
-
- /*
- ** Verify that we got all the needed variables. Needed because some
- ** implementations of nlist() returns 0 although it didn't find all
- ** variables.
- */
- if (code == 0)
- {
-#if defined(__convex__) || defined(NeXT)
- for (i = 0; nl[i].n_un.n_name && nl[i].n_un.n_name[0]; i++)
-#else
- for (i = 0; nl[i].n_name && nl[i].n_name[0]; i++)
-#endif
-#if defined(_AUX_SOURCE) || defined(_CRAY) || defined(sco) || defined(_SEQUENT_)
- /* A/UX sets n_type to 0 if not compiled with -g. n_value will still
- ** contain the (correct?) value (unless symbol unknown).
- */
- if( nl[i].n_value == 0)
- code++;
-#else
- if (nl[i].n_type == 0)
- code++;
-#endif
- }
-
- return code;
-}
-
-
-/*
-** Get a piece of the kernel memory
-*/
-static int readbuf(fd, addr, buf, len)
- int fd;
- long addr;
- char *buf;
- int len;
-{
-#ifdef IRIX
- addr = K0_TO_PHYS(addr);
-#endif
- errno = 0;
-#if defined(__alpha)
- /*
- * Let us be paranoid about return values.
- * It should be like this on all implementations,
- * but some may have broken lseek or read returns.
- */
- if (lseek(fd, addr, 0) != addr || errno != 0) return -1;
- if (read(fd, buf, len) != len || errno != 0) return -1;
- return len;
-#else
- if (lseek(fd, addr, 0) == -1 && errno != 0) return -1;
- return read(fd, buf, len);
-#endif
-}
-
-int kvm_read(kd, addr, buf, len)
- kvm_t *kd;
- long addr;
- char *buf;
- int len;
-{
- return readbuf(kd->fd, addr, buf, len);
-}
-
-
-#ifdef BSD43
-
-struct user *kvm_getu(kd, procp)
- kvm_t *kd;
- struct proc *procp;
-{
- static union
- {
- struct user user;
- char upages[UPAGES][NBPG];
- } userb;
-
- int ncl;
- struct pte *pteaddr, apte;
- struct pte arguutl[UPAGES+CLSIZE];
-
-
- if ((procp->p_flag & SLOAD) == 0)
- {
- if(readbuf(kd->swap_fd,
- dtob(procp->p_swaddr),
- &userb.user, sizeof(struct user)) < 0)
- return NULL;
- }
- else
- {
- /*
- ** Sigh. I just *love* hard coded variable names in macros...
- */
- {
- struct pte *usrpt = kd->usrpt;
-
- pteaddr = &kd->Usrptma[btokmx(procp->p_p0br) + procp->p_szpt - 1];
- if (readbuf(kd->fd, pteaddr, &apte, sizeof(apte)) < 0)
- return NULL;
- }
-
- if (readbuf(kd->mem_fd,
- ctob(apte.pg_pfnum+1)-(UPAGES+CLSIZE)*sizeof(struct pte),
- arguutl, sizeof(arguutl)) < 0)
- return NULL;
-
- ncl = (sizeof(struct user) + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
- while (--ncl >= 0)
- {
- int i;
-
-
- i = ncl * CLSIZE;
- if(readbuf(kd->mem_fd,
- ctob(arguutl[CLSIZE+i].pg_pfnum),
- userb.upages[i], CLSIZE*NBPG) < 0)
- return NULL;
- }
- }
-
- return &userb.user;
-}
-
-
-
-struct proc *kvm_nextproc(kd)
- kvm_t *kd;
-{
- if (kd->proctab == NULL)
- if (kvm_setproc(kd) < 0)
- return NULL;
-
- if (kd->procidx < kd->nproc)
- return &kd->proctab[kd->procidx++];
-
- return (struct proc *) NULL;
-}
-
-int kvm_setproc(kd)
- kvm_t *kd;
-{
- long procaddr;
-
- static struct nlist nl[] =
- {
-#define N_PROC 0
-#define N_USRPTMA 1
-#define N_NPROC 2
-#define N_USRPT 3
-
- { "_proc" },
- { "_Usrptmap" },
- { "_nproc" },
- { "_usrpt" },
- { "" }
- };
-
- if (kvm_nlist(kd, nl) != 0)
- return -1;
-
- kd->Usrptma = (struct pte *) nl[N_USRPTMA].n_value;
- kd->usrpt = (struct pte *) nl[N_USRPT].n_value;
-
- if (readbuf(kd->fd, nl[N_NPROC].n_value, &kd->nproc, sizeof(kd->nproc)) < 0)
- return -1;
-
- if (readbuf(kd->fd, nl[N_PROC].n_value, &procaddr, sizeof(procaddr)) < 0)
- return -1;
-
- if (kd->proctab)
- free(kd->proctab);
-
- kd->proctab = (struct proc *) calloc(kd->nproc, sizeof(struct proc));
- if (!kd->proctab)
- return -1;
-
- if (readbuf(kd->fd,
- procaddr,
- kd->proctab,
- kd->nproc*sizeof(struct proc)) < 0)
- return -1;
-
- kd->procidx = 0;
-
- return 0;
-}
-
-
-struct proc *kvm_getproc(kd, pid)
- kvm_t *kd;
- int pid;
-{
- struct proc *procp;
-
-
- if (kvm_setproc(kd) < 0)
- return NULL;
-
- while ((procp = kvm_nextproc(kd)) && procp->p_pid != pid)
- ;
-
- return procp;
-}
-
-#endif
-
-#else
-/* Just to make some compilers shut up! */
-int kvm_dummy()
-{
- return 1;
-}
-#endif /* HAVE_LIBKVM */
-#endif /* NO_KVM */
*/
#include <time.h>
-#include <krb.h>
+
+#ifdef HAVE_KERBEROSIV_KRB_H
+# include <kerberosIV/krb.h>
+#else
+# include <krb.h>
+#endif
/** The lifetime value indicating a ticket that never expires. */
#define TKTLIFENOEXPIRE 0xFF
* $Id$
*/
-#include <ctype.h>
#include <errno.h>
#include <pwd.h>
#include <setjmp.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
-#include <sys/time.h>
#include <sys/types.h>
+#include <syslog.h>
#include <unistd.h>
/* BSDI needs <netinet/in.h> before <arpa/inet.h>. */
#include <netinet/in.h>
#include <arpa/inet.h>
-#include "error.h"
#include "identd.h"
#include "sident.h"
-#include "pidentd.h"
+#include "pidentd.h"
+
+/* The number of times to retry a kernel lookup before failing. */
+#define MAX_RETRY 20
extern int do_error();
extern int parse_auth();
-/*
-** A small routine to check for the existance of the ".nosident"
-** file in a users home directory.
-*/
-static int check_nosident(uid_t uid)
+/* Check for the existence of a ".nosident" file in a user's home directory.
+ Return whether one was found. */
+static int
+check_nosident(uid_t uid)
{
- char *tmp_path,*homedir;
- struct stat sbuf;
- int rcode;
- struct passwd *pw ;
-
- if ( users_can_nosident ) {
-
- pw = getpwuid(uid);
-
- if ( pw == NULL )
- return 0 ;
+ char *tmp_path, *homedir;
+ struct stat sbuf;
+ int rcode;
+ struct passwd *pw;
+
+ if (users_can_nosident) {
+ pw = getpwuid(uid);
+ if (pw == NULL)
+ return 0;
+ homedir = pw->pw_dir;
+ if (homedir == NULL)
+ return 0;
+ tmp_path = malloc(strlen(homedir) + sizeof("/.nosident") + 1);
+ if (tmp_path == NULL)
+ return 0;
+ strcpy(tmp_path, homedir);
+ strcat(tmp_path, "/.nosident");
+ rcode = stat(tmp_path, &sbuf);
+ free(tmp_path);
+ return (rcode == 0);
+ } else
+ return 0;
+}
- homedir = pw->pw_dir ;
+/* Timeout handling for sfgets. */
+static jmp_buf context_read_timeout;
+static void
+readtimeout(int sig)
+{
+ longjmp(context_read_timeout, 1);
+}
- if (!homedir)
- return 0;
- tmp_path = (char *) malloc(strlen(homedir) + sizeof("/.nosident") + 1);
- if (!tmp_path)
- return 0;
+/*
+** An implementation of fgets that ignores EINTR interrupts and implements a
+** timeout. Takes a buffer, the size of the buffer, the file to read from,
+** the timeout in seconds, and the authentication we're trying to perform
+** (for error reporting). Returns NULL on error and a pointer to the buffer
+** otherwise.
+**
+** This function needs to be rewritten to use select instead of setjmp and
+** alarm. Not only will that be easier to read, it will also be more
+** reliable and understandable.
+*/
+char *
+sfgets(char *buf, int siz, FILE *fp, time_t timeout,
+ struct ident_auth_data *auth_data)
+{
+ char *p;
- strcpy(tmp_path, homedir);
- strcat(tmp_path, "/.nosident");
+ if (fp == NULL) {
+ buf[0] = '\0';
+ return NULL;
+ }
- rcode = stat(tmp_path, &sbuf);
- free(tmp_path);
+ /* Set the timeout. */
+ if (timeout != 0) {
+ if (signal(SIGALRM, readtimeout) == SIG_ERR)
+ do_error(IDENT_SYSTEM_ERROR, auth_data);
+ if (setjmp(context_read_timeout) != 0) {
+ syslog(LOG_NOTICE, "timeout waiting for input");
+ errno = 0;
+ buf[0] = '\0';
+ return NULL;
+ }
+ alarm(timeout);
+ }
- return (rcode == 0);
- } else {
- return ( 1 == 0 ) ;
- }
+ /* Try to read. */
+ p = NULL;
+ while (!feof(fp) && !ferror(fp)) {
+ errno = 0;
+ p = fgets(buf, siz, fp);
+ if (p != NULL || errno != EINTR)
+ break;
+ clearerr(fp);
+ }
+ alarm(0);
+ if (verbose_flag)
+ syslog(LOG_DEBUG, "In function sfgets :%d:%s:%s", siz, buf, p);
+ return buf;
}
/*
-** Borrowed from Sendmail.8.8
-** SFGETS -- "safe" fgets -- times out and ignores random interrupts.
-**
-** Parameters:
-** buf -- place to put the input line.
-** siz -- size of buf.
-** fp -- file to read from.
-** timeout -- the timeout before error occurs.
-** during -- what we are trying to read (for error messages).
-**
-** Returns:
-** NULL on error (including timeout). This will also leave
-** buf containing a null string.
-** buf otherwise.
-**
-** Side Effects:
-** none.
+** Parse an incoming line. If it contains authentication information, run
+** parse_auth to handle it. Sets various things in the auth_data struct.
*/
-
-static jmp_buf CtxReadTimeout;
-static void readtimeout();
-
-char *
-sfgets(buf, siz, fp, timeout,auth_data)
- char *buf;
- int siz;
- FILE *fp;
- time_t timeout;
- struct ident_auth_data *auth_data ;
+int
+parse_auth_line(char *line, struct ident_auth_data *auth_data)
{
+ char arg[33];
+ int rcode;
+ char *p;
- register char *p;
-
- if (fp == NULL)
- {
- buf[0] = '\0';
- return NULL;
- }
-
- /* set the timeout */
- if (timeout != 0)
- {
- if (signal(SIGALRM, readtimeout) == SIG_ERR)
- do_error(IDENT_SYSTEM_ERROR,auth_data) ;
- if (setjmp(CtxReadTimeout) != 0)
- {
- syslog(LOG_NOTICE,
- "timeout waiting for input");
- errno = 0;
-
- buf[0] = '\0';
- return (NULL);
- }
- alarm(timeout);
- }
-
- /* try to read */
- p = NULL;
- while (!feof(fp) && !ferror(fp))
- {
- errno = 0;
- p = fgets(buf, siz, fp);
- if (p != NULL || errno != EINTR)
- break;
- clearerr(fp);
- }
-
- /* clear the event if it has not sprung */
-
- alarm(0);
-
- if (verbose_flag)
- syslog(LOG_DEBUG, "In function sfgets :%d:%s:%s",siz,buf,p);
-
- return (buf);
+ p = strtok(line, ": ");
+ if (verbose_flag)
+ syslog(LOG_DEBUG, "parse_auth_line: %s: port_data %s", line, p);
+ if (p != NULL)
+ auth_data->port_data = p;
+ else
+ return IDENT_INVALID_PORT;
+
+ p = strtok(NULL, ": ");
+ auth_data->cmd_data = p;
+
+ p = strtok(NULL, ": ");
+ auth_data->authenticate_data = p;
+
+ /* Parse the port data into numbers. */
+ rcode = sscanf(auth_data->port_data, " %d , %d ", &auth_data->local_port,
+ &auth_data->remote_port);
+ if (rcode < 2)
+ return IDENT_INVALID_REQ_INFO;
+
+ /* If we have a command, parse it into a variable and then see if it's an
+ AUTHENTICATE commad. If not, it's a trivial auth request. */
+ if (auth_data->cmd_data != NULL)
+ rcode = sscanf(auth_data->cmd_data, " %32s ", arg);
+ else
+ rcode = 0;
+ if (rcode > 0) {
+ if (strcmp(arg, "AUTHENTICATE") == 0
+ && auth_data->authenticate_data != NULL) {
+ if (verbose_flag)
+ syslog(LOG_DEBUG, "About to parse %s",
+ auth_data->authenticate_data);
+ rcode = parse_auth(auth_data->authenticate_data,
+ &auth_data->auth_struct);
+ return rcode;
+ } else
+ return IDENT_INVALID_REQ_INFO;
+ } else if (allow_trivial) {
+ rcode = parse_auth(NULL, &auth_data->auth_struct);
+ return rcode;
+ } else
+ return IDENT_UNKNOWN_ERROR;
}
-static void
-readtimeout(sig_no)
- int sig_no;
+
+/*
+** Send a response back to the requester. Takes the response and the
+** auth_data struct (used to fill out the port details). Always returns
+** true.
+*/
+int
+do_out(char *string, struct ident_auth_data *auth_data)
{
- longjmp(CtxReadTimeout, 1);
+ printf(" %d , %d : %s\r\n", auth_data->local_port,
+ auth_data->remote_port, string);
+ if (verbose_flag)
+ syslog(LOG_DEBUG, " %d , %d : %s", auth_data->local_port,
+ auth_data->remote_port, string);
+ fflush(stdout);
+ return 1;
}
+
/*
-** Parse incoming lines
+** Return an error reply to the requester and log the error. Takes the error
+** code and the auth_data struct (used to fill out the port details). Does
+** not return; exit is called with the error code.
**
+** If the error code is above IDENT_INTERNAL_ERR, no reply is sent and the
+** connection is just immediately closed.
*/
-int
-parse_auth_line(line,auth_data)
-char *line;
-struct ident_auth_data *auth_data ;
-{
- char arg[33] ;
- int rcode ;
- char *p ;
- char delim[] = ":" ;
-
- p = strtok(line,delim);
- if (verbose_flag)
- syslog(LOG_DEBUG, "In function parse_auth_line:%s:port_data %s",line,p);
-
- if ( p != NULL ) {
- auth_data->port_data = p ;
- } else {
- return IDENT_INVALID_PORT ;
- }
-
- p = strtok((char *) NULL,delim);
- auth_data->cmd_data = p ;
-
- p = strtok((char *) NULL,delim);
- auth_data->authenticate_data = p ;
-
- if ( auth_data->port_data != NULL ) {
- rcode = sscanf(auth_data->port_data, " %d , %d ", &(auth_data->local_port),
- &(auth_data->remote_port));
- } else {
- return IDENT_INVALID_PORT ;
- }
- if ( rcode > 0 ) {
- if (auth_data->cmd_data != NULL ) {
- rcode = sscanf(auth_data->cmd_data," %32s ",arg ) ;
+int
+do_error(int e_code, struct ident_auth_data *auth_data)
+{
+ char tmp[2048];
+ int show_code;
+
+ if (e_code < IDENT_INTERNAL_ERR) {
+ show_code = e_code;
+ if (unknown_flag)
+ if (e_code == IDENT_NO_USER || e_code == IDENT_INVALID_PORT)
+ show_code = IDENT_UNKNOWN_ERROR;
+ sprintf(tmp, " ERROR : %s ", ident_err_txt[show_code]);
+ do_out(tmp, auth_data);
+ if (syslog_flag)
+ syslog(LOG_INFO, "Error: %s", ident_err_txt[e_code]);
} else {
- rcode = 0 ;
+ switch (e_code) {
+ case IDENT_NO_MUTUAL_AUTH:
+ if (syslog_flag)
+ syslog(LOG_INFO, "No mutual auth data");
+ break;
+ case IDENT_MUTUAL_AUTH_FAIL:
+ if (syslog_flag)
+ syslog(LOG_INFO, "Mutual auth failed");
+ break;
+ case IDENT_SYSTEM_ERROR:
+ if (syslog_flag)
+ syslog(LOG_INFO, "System error: %m");
+ break;
+ default:
+ if (syslog_flag)
+ syslog(LOG_INFO, "Unknown error code %d", e_code);
+ break;
+ }
}
- if ( rcode > 0 ) {
- if (( strncmp(arg,"AUTHENTICATE",strlen("AUTHENTICATE")) == 0)
- && (auth_data->authenticate_data != NULL) ) {
- if (verbose_flag)
- syslog(LOG_DEBUG, "About to parse %s", auth_data->authenticate_data);
- rcode = parse_auth(auth_data->authenticate_data,&(auth_data->auth_struct)) ;
- return rcode ;
- } else {
- return IDENT_INVALID_REQ_INFO ;
- }
- } else if ( allow_trivial ) {
- rcode = parse_auth(NULL,&(auth_data->auth_struct)) ;
- return rcode ;
- } else {
- return IDENT_UNKNOWN_ERROR ;
- }
- } else {
- return IDENT_SYSTEM_ERROR;
- }
-
+ exit(e_code);
}
-int
-do_out(string , auth_data)
-char *string ;
-struct ident_auth_data *auth_data ;
-{
- printf(" %d , %d : %s\r\n", auth_data->local_port,auth_data->remote_port,string);
- if (verbose_flag)
- syslog(LOG_DEBUG," %d , %d : %s", auth_data->local_port,auth_data->remote_port,string );
-
- fflush(stdout);
- return 1;
-}
-/*
-** Handle ERROR codes
+
+
+/*
+** The core of the S/Ident daemon. Parse the incoming request from the
+** requester and take appropriate action. This is also where we do the
+** kernel query to flesh out the details of the request before passing them
+** off to the handlers for the different authentication methods.
**
+** Takes the FILE of the remote connection, the local Internet address, and
+** the remote Internet address (used in the kernel query). Always returns 0;
+** on error, this function will never return.
*/
-int
-do_error(e_code,auth_data)
- int e_code ;
- struct ident_auth_data *auth_data ;
-{
- char tmp[2048] ;
- int show_code ;
- if ( e_code < IDENT_INTERNAL_ERR ) {
- show_code = e_code ;
- if ( unknown_flag )
- if ( e_code == IDENT_NO_USER || e_code == IDENT_INVALID_PORT )
- show_code = IDENT_UNKNOWN_ERROR ;
- sprintf(tmp," ERROR : %s ", ident_err_txt[show_code]);
- do_out(tmp,auth_data);
-
- if ( syslog_flag)
- syslog(LOG_INFO, "Error : %s", ident_err_txt[e_code]);
-
- } else {
- /* Need to syslog errors here */
- switch(e_code) {
- case IDENT_NO_MUTUAL_AUTH:
- if ( syslog_flag)
- syslog(LOG_INFO, " No mutual auth data");
- break;
- case IDENT_MUTUAL_AUTH_FAIL:
- if ( syslog_flag)
- syslog(LOG_INFO, " Mutual auth failed" );
- break ;
- case IDENT_SYSTEM_ERROR:
- if ( syslog_flag)
- syslog(LOG_INFO, " System error" );
- break ;
-
- default:
- if (syslog_flag)
- syslog(LOG_INFO, " Unknown error code %d",e_code );
- ;
- }
- }
- exit(e_code);
-
-}
-
-
-
-int parse(fp, laddr, faddr)
- FILE *fp;
- struct in_addr *laddr, *faddr;
+int
+parse(FILE *fp, struct in_addr *laddr, struct in_addr *faddr)
{
- int try, rcode;
- int timeout = IDENT_READ_TIMEOUT ;
-
- struct ident_auth_data auth_data ;
-
- struct in_addr laddr2;
- struct in_addr faddr2;
- int k_opened;
- char line[2048];
- char *line_ptr ;
- void *ka_ptr ;
- struct kernel *kinfo_ptr ;
-
- k_opened = 0;
-
- if (verbose_flag)
- syslog(LOG_DEBUG, "In function parse()");
-
- /*
- ** Get the local/foreign port pair from the luser
- */
-
- if (verbose_flag)
- syslog(LOG_DEBUG, " Before sfgets()");
-
- faddr2 = *faddr;
- laddr2 = *laddr;
-
- auth_data.local_addr = &laddr2;
- auth_data.remote_addr = &faddr2;
- auth_data.fp = fp ;
-
- auth_data.local_port = auth_data.remote_port = 0;
-
- /* Read query from client */
- line_ptr = line ;
-
- line_ptr = sfgets(line,2048,fp,timeout,&auth_data);
- if (verbose_flag)
- syslog(LOG_DEBUG, "After sfgets line_ptr:%s",line_ptr);
-
- if ( line_ptr == NULL ) {
- do_error(IDENT_SYSTEM_ERROR,&auth_data);
- }
- rcode = parse_auth_line(line_ptr,&auth_data);
- if ( rcode != IDENT_AUTH_OKAY ) {
- do_error(rcode,&auth_data);
- }
-
-
- if (!( VALID_PORT(auth_data.local_port) && VALID_PORT(auth_data.remote_port))) {
- do_error(IDENT_INVALID_PORT,&auth_data);
- }
-
- if ( client_only_flag ) {
- if( SERVER_PORT(auth_data.local_port) ) {
- do_error(IDENT_NO_USER,&auth_data);
- }
- }
-
- if (syslog_flag) {
- syslog(LOG_NOTICE, "from: %s ( %s ) for: %d, %d",
- inet_ntoa(*faddr), gethost(faddr), auth_data.local_port, auth_data.remote_port);
- }
-
- if (verbose_flag)
- syslog(LOG_DEBUG, " After fscanf(), before k_open()");
-
- if (! k_opened) {
- /*
- ** Open the kernel memory device and read the nlist table
- **
- ** Converted to use the ka_open routines from pidentd.3.0.x
- */
- if (ka_open(&ka_ptr) != 0) {
- if (syslog_flag)
- syslog(LOG_ERR, "ka_open call failed");
- do_error(IDENT_UNKNOWN_ERROR,auth_data);
-
- }
- k_opened = 1;
- }
-
- if (verbose_flag)
- syslog(LOG_DEBUG, " After ka_open(), before ka_lookup()");
-
- /*
- ** Get the specific TCP connection and return the uid - user number.
- */
+ int try, rcode;
+ int timeout = IDENT_READ_TIMEOUT;
+ struct ident_auth_data auth_data;
+ char line[2048];
+ char *line_ptr;
+ void *ka_ptr;
+ struct kernel *kinfo_ptr;
-#define MAX_RETRY 20
- /*
- ** Try to fetch the information MAX_RETRY times in case the
- ** kernel changed beneath us and we missed or took a fault.
- **
- ** Why would we ever fail? Is not there a reliable way for the
- ** kernel to identify its sockets? Cannot we use that interface?
- **
- ** Used to be 5 times, but often this is not enough on Alpha OSF.
- */
- /* #define SLEEP_BETWEEN_RETRIES 1 */
- /*
- ** If we failed in k_getuid, that is presumably because the OS was
- ** busy creating or destroying processes. We may want to sleep for
- ** a random time between retries, hoping for peace and quiet.
- */
-
- /* Fill up kernel info struct */
-
- /* struct kernel */
- /* { */
- /* Request parameters */
- /* struct sockaddr_in local; */
- /* struct sockaddr_in remote; */
-
- /* Result parameters */
- /* avail_t av; */
-
- /* int status; */
- /* uid_t euid; */
- /* uid_t ruid; */
-
- /* pid_t pid; */
- /* char *cmd; */
- /* char *argv; */
- /* }; */
-
- kinfo_ptr = kernel_alloc() ;
-
- if ( kinfo_ptr == NULL ) {
- if (syslog_flag)
- syslog(LOG_ERR, "kernel_alloc call failed");
- do_error(IDENT_UNKNOWN_ERROR,auth_data);
- }
-
- kinfo_ptr->local.sin_port = htons(auth_data.local_port) ;
- kinfo_ptr->remote.sin_port = htons(auth_data.remote_port) ;
- memcpy(&(kinfo_ptr->local.sin_addr),auth_data.local_addr,sizeof(struct in_addr));
- memcpy(&(kinfo_ptr->remote.sin_addr),auth_data.remote_addr,sizeof(struct in_addr));
- kinfo_ptr->local.sin_family = AF_INET ;
- kinfo_ptr->remote.sin_family = AF_INET ;
- /* ka_lookup returns 0 on not-found,1 on found, -1 on failure. */
- kinfo_ptr->status = -1 ;
-
- for (try = 0;(try < MAX_RETRY && kinfo_ptr->status < 0); try++) {
- kinfo_ptr->status = ka_lookup(ka_ptr,kinfo_ptr) ;
-
-#ifdef SLEEP_BETWEEN_RETRIES
- if ( kinfo_ptr->status < 0 ) {
- /* Seed the generator: auth_data.local_port should be unique (among other concurrent identd's) */
- if (try < 1) srandom(auth_data.local_port);
- /* This gives a max sleep of 0xffff = 65535 microsecs, about 32millisec average */
- usleep(random()&0x00ffff);
- }
-#endif
- }
- if (try >= MAX_RETRY) {
- if (syslog_flag)
- syslog(LOG_INFO, "MAX_RETRY exceeded,Returned: %d , %d : NO-USER", auth_data.local_port, auth_data.remote_port);
- do_error(IDENT_NO_USER,&auth_data);
- }
-
- if (try > 1 && verbose_flag)
- syslog(LOG_DEBUG, "ka_lookup retries: %d", try);
-
- if (verbose_flag)
- syslog(LOG_DEBUG, " After ka_lookup(), before getpwuid() kinfo_ptr status = %d",kinfo_ptr->status);
-
- if ( kinfo_ptr->status == 0 ) {
- do_error(IDENT_NO_USER,&auth_data);
- }
-
- if (kinfo_ptr->ruid == NO_UID)
- auth_data.uid = kinfo_ptr->euid;
- else
- auth_data.uid = kinfo_ptr->ruid;
-
-
- if ( auth_data.uid > -1 ) {
- /* Setuid here ??? */
-
- if ( setuid(auth_data.uid) != 0 ) {
- syslog(LOG_ALERT,"Setuid failed for uid:%d",auth_data.uid);
- do_error(IDENT_UNKNOWN_ERROR,&auth_data);
- }
- /* Check for .nosident */
- if( check_nosident(auth_data.uid) ) {
- syslog(LOG_DEBUG,"No ident requested by uid:%d",auth_data.uid) ;
- do_error(IDENT_HIDDEN_USER,&auth_data);
- }
- } else {
+ if (verbose_flag)
+ syslog(LOG_DEBUG, "In function parse");
+ auth_data.local_addr = laddr;
+ auth_data.remote_addr = faddr;
+ auth_data.fp = fp;
+ auth_data.local_port = 0;
+ auth_data.remote_port = 0;
+
+ /* Read query from client and parse it. */
+ line_ptr = sfgets(line, 2048, fp, timeout, &auth_data);
+ if (verbose_flag)
+ syslog(LOG_DEBUG, "After sfgets line_ptr: %s", line_ptr);
+ if (line_ptr == NULL)
+ do_error(IDENT_SYSTEM_ERROR, &auth_data);
+ rcode = parse_auth_line(line_ptr, &auth_data);
+ if (rcode != IDENT_AUTH_OKAY)
+ do_error(rcode, &auth_data);
+
+ /* Validate the ports in the query. */
+ if (!VALID_PORT(auth_data.local_port)
+ || !VALID_PORT(auth_data.remote_port))
+ do_error(IDENT_INVALID_PORT,&auth_data);
+ if (client_only_flag)
+ if (SERVER_PORT(auth_data.local_port))
+ do_error(IDENT_NO_USER, &auth_data);
+
+ /* Log the query. */
if (syslog_flag)
- syslog(LOG_INFO, "INVALID uid %d",auth_data.uid);
- do_error(IDENT_UNKNOWN_ERROR,&auth_data);
- }
+ syslog(LOG_NOTICE, "from: %s (%s), for: %d, %d",
+ inet_ntoa(*faddr), gethost(faddr), auth_data.local_port,
+ auth_data.remote_port);
- if (syslog_flag)
- syslog(LOG_INFO, "AUTHENTICATE with %s",auth_data.auth_struct->auth_method);
-
- rcode = (*auth_data.auth_struct->start)(&auth_data);
- if ( rcode != IDENT_AUTH_OKAY ) {
+ /* Open the kernel and find the associated user. */
if (verbose_flag)
- syslog(LOG_DEBUG, " Fail in auth_start");
- do_error(rcode,&auth_data);
- }
-
- rcode = (*auth_data.auth_struct->auth)(&auth_data);
- if ( rcode != IDENT_AUTH_OKAY ) {
+ syslog(LOG_DEBUG, "After parsing, before k_open");
+ if (ka_open(&ka_ptr) != 0) {
+ if (syslog_flag)
+ syslog(LOG_ERR, "ka_open call failed");
+ do_error(IDENT_UNKNOWN_ERROR, &auth_data);
+ }
if (verbose_flag)
- syslog(LOG_DEBUG, " Fail in auth_auth");
- do_error(rcode,&auth_data);
- }
- return 0;
+ syslog(LOG_DEBUG, "After ka_open, before ka_lookup");
+
+ /* Get the specific TCP connection and return the uid.
+
+ Try to fetch the information MAX_RETRY times in case the kernel changed
+ beneath us and we missed or took a fault. Used to be 5 times, but
+ often this is not enough on Alpha OSF.
+
+ If we failed in ka_lookup, that is presumably because the OS was busy
+ creating or destroying processes. We may want to sleep for a random
+ time between retries, hoping for peace and quiet, but we don't
+ currently. */
+ kinfo_ptr = kernel_alloc();
+ if (kinfo_ptr == NULL) {
+ if (syslog_flag)
+ syslog(LOG_ERR, "kernel_alloc call failed");
+ do_error(IDENT_UNKNOWN_ERROR, &auth_data);
+ }
+ kinfo_ptr->local.sin_port = htons(auth_data.local_port);
+ kinfo_ptr->remote.sin_port = htons(auth_data.remote_port);
+ memcpy(&kinfo_ptr->local.sin_addr, auth_data.local_addr,
+ sizeof(struct in_addr));
+ memcpy(&kinfo_ptr->remote.sin_addr, auth_data.remote_addr,
+ sizeof(struct in_addr));
+ kinfo_ptr->local.sin_family = AF_INET ;
+ kinfo_ptr->remote.sin_family = AF_INET ;
+ kinfo_ptr->status = -1;
+
+ /* status will be set to 0 on not found, 1 on found, and -1 on failure. */
+ for (try = 0; try < MAX_RETRY && kinfo_ptr->status < 0; try++)
+ kinfo_ptr->status = ka_lookup(ka_ptr, kinfo_ptr);
+ if (try >= MAX_RETRY) {
+ if (syslog_flag)
+ syslog(LOG_INFO,
+ "MAX_RETRY exceeded, returned: %d , %d : NO-USER",
+ auth_data.local_port, auth_data.remote_port);
+ do_error(IDENT_NO_USER, &auth_data);
+ }
+ if (try > 1 && verbose_flag)
+ syslog(LOG_DEBUG, "ka_lookup retries: %d", try);
+ if (verbose_flag)
+ syslog(LOG_DEBUG, "after ka_lookup, before getpwuid,"
+ " kinfo_ptr status = %d", kinfo_ptr->status);
+ if (kinfo_ptr->status == 0)
+ do_error(IDENT_NO_USER,&auth_data);
+
+ /* Try to use the real, not the effective, UID where possible. */
+ if (kinfo_ptr->ruid == NO_UID)
+ auth_data.uid = kinfo_ptr->euid;
+ else
+ auth_data.uid = kinfo_ptr->ruid;
+
+ /* If we found a valid UID, change users. We can do everything from this
+ point forward as the user whose information is being looked up. Check
+ for the user's .nosident file at this point as well. */
+ if (auth_data.uid > -1) {
+ if (setuid(auth_data.uid) != 0) {
+ syslog(LOG_ALERT, "setuid failed for uid %d", auth_data.uid);
+ do_error(IDENT_UNKNOWN_ERROR, &auth_data);
+ }
+ if (check_nosident(auth_data.uid)) {
+ syslog(LOG_DEBUG, "no ident requested by uid %d", auth_data.uid);
+ do_error(IDENT_HIDDEN_USER, &auth_data);
+ }
+ } else {
+ if (syslog_flag)
+ syslog(LOG_INFO, "invalid uid %d", auth_data.uid);
+ do_error(IDENT_UNKNOWN_ERROR, &auth_data);
+ }
+
+ /* We have a valid request. Now do the real work. */
+ if (syslog_flag)
+ syslog(LOG_INFO, "AUTHENTICATE with %s",
+ auth_data.auth_struct->auth_method);
+ rcode = (*auth_data.auth_struct->start)(&auth_data);
+ if (rcode != IDENT_AUTH_OKAY) {
+ if (verbose_flag)
+ syslog(LOG_DEBUG, "fail in auth_start");
+ do_error(rcode, &auth_data);
+ }
+ rcode = (*auth_data.auth_struct->auth)(&auth_data);
+ if (rcode != IDENT_AUTH_OKAY) {
+ if (verbose_flag)
+ syslog(LOG_DEBUG, "fail in auth_auth");
+ do_error(rcode, &auth_data);
+ }
+ return 0;
}
+++ /dev/null
-/*
-** paths.h Common path definitions for the in.identd daemon
-**
-** Last update: 11 Dec 1992
-**
-** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
-*/
-
-#ifdef sequent
-# define _PATH_UNIX "/dynix"
-#endif
-
-#if defined(MIPS) || defined(IRIX) || defined(sco) || defined(_SEQUENT_)
-# define _PATH_UNIX "/unix"
-#endif
-
-#if defined(hpux) || defined(__hpux)
-#ifdef HPUX_10
-# define _PATH_UNIX "/stand/vmunix"
-#else
-# define _PATH_UNIX "/hp-ux"
-#endif
-#endif
-
-#ifdef SOLARIS
-# define _PATH_UNIX "/dev/ksyms"
-#else
-# if defined(SVR4) && !defined(_SEQUENT_)
-# define _PATH_UNIX "/stand/unix"
-# endif
-#endif
-
-#ifdef BSD43
-# define _PATH_SWAP "/dev/drum"
-# define _PATH_MEM "/dev/mem"
-#endif
-
-#ifdef _AUX_SOURCE
-# define _PATH_UNIX "/unix"
-#endif
-
-#ifdef _CRAY
-# define _PATH_UNIX "/unicos"
-# define _PATH_MEM "/dev/mem"
-#endif
-
-#ifdef NeXT
-# define _PATH_UNIX "/mach"
-#endif
-
-#ifdef __bsdi__
-# define _PATH_UNIX "/bsd"
-#endif /* __bsdi__ */
-
-
-/*
- * Some defaults...
- */
-#ifndef _PATH_KMEM
-# define _PATH_KMEM "/dev/kmem"
-#endif
-
-#ifndef _PATH_UNIX
-# define _PATH_UNIX "/vmunix"
-#endif
-
-
-#ifndef PATH_CONFIG
-# define PATH_CONFIG "/etc/identd.conf"
-#endif
-
-#ifndef PATH_DESKEY
-# define PATH_DESKEY "/etc/identd.key"
-#endif
/** @file
* Provides necessary glue in order to use pidentd kernel files.
*
- * This file provides the glue necessary to use pident3.* k_os files with
+ * This file provides the glue necessary to use pident 3.* k_os files with
* S/Ident without any changes to the k_os files.
*
* $Id$
- */
+ */
#ifndef PIDENTD_H
#define PIDENTD_H
#define NO_UID ((uid_t) -1)
#define NO_PID ((pid_t) -1)
-#ifndef KERNEL_HELPER
-extern char *osinfo_build ;
-#endif
-
-char *osinfo_get( char *osinfo_current) ;
-
-void *s_malloc( size_t size ) ;
-void s_free( void *ptr) ;
-
-char *s_strdup(const char *dup_string ) ;
-
-struct kernel
-{
- /* Request parameters */
+/* Taken from pidentd's sockaddr.h, the non-IPv6 case. Eventually we'll have
+ to pull in the IPv6 pieces, but sident needs a bunch more work to support
+ IPv6. These are used by the Solaris modules. */
+#define SGFAM(sag) AF_INET
+#define SGSIZE(sag) sizeof(struct in_addr)
+#define SGSOCKSIZE(sag) sizeof(struct sockaddr_in)
+#define SGPORT(sag) ((sag).sin_port)
+#define SGADDRP(sag) ((char *) &(sag).sin_addr)
+
+/* Only used by ka_init, which we don't call. */
+extern const char *osinfo_build;
+char *osinfo_get(char *osinfo_current);
+
+/* Various safe versions of regular functions used by the kernel modules. */
+void *s_malloc(size_t);
+void s_free(void *);
+char *s_strdup(const char *);
+int s_open(const char *, int, ...);
+int s_snprintf(char *, size_t, const char *, ...);
+
+/* Used as the interface to the kernel routines. This matches the kernel
+ struct in pidentd 3.x except that we omit the av parameter, since none of
+ the kernel modules actually use it (it's a thread mutex). */
+struct kernel {
struct sockaddr_in local;
struct sockaddr_in remote;
/* Result parameters */
-
int status;
uid_t euid;
uid_t ruid;
char *argv;
};
+/* Filled in by ka_init for some drivers. We don't use them, but they have to
+ be here to compile the kernel modules. */
extern int kernel_threads;
extern int kernel_buffers;
extern int kernel_attempts;
+/* The kernel modules use debug instead of debug_flag. */
+extern int debug_flag;
+#define debug debug_flag
+
+/* These interface functions we actually call in the sident code. */
extern struct kernel *kernel_alloc(void);
extern void kernel_free(struct kernel *kp);
-extern int kernel_init(void);
-extern void kernel_query(struct kernel *kp);
-
-
-/*
-** Operating system specific kernel access functions
-*/
+/* The kernel modules provide the following three functions. We never call
+ ka_init, but we do use the other two. */
extern int ka_init(void);
extern int ka_open(void **misc);
extern int ka_lookup(void *misc, struct kernel *kp);