Add samba4kpasswd and rkpty binaries
authorAndrew Bartlett <abartlet@samba.org>
Mon, 20 Oct 2008 01:18:01 +0000 (12:18 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 20 Oct 2008 09:07:08 +0000 (20:07 +1100)
smaba4kpasswd will be used to test the kpasswdd componet of the KDC
(which is up until now untested), and rkpty is an expect-like wrapper
we can use to blackbox that utility.

Andrew Bartlett

source4/heimdal/kpasswd/kpasswd.c [new file with mode: 0644]
source4/heimdal/kpasswd/kpasswd_locl.h [new file with mode: 0644]
source4/heimdal/lib/krb5/prog_setup.c [new file with mode: 0644]
source4/heimdal/lib/roken/rkpty.c [new file with mode: 0644]
source4/heimdal_build/internal.m4
source4/heimdal_build/internal.mk

diff --git a/source4/heimdal/kpasswd/kpasswd.c b/source4/heimdal/kpasswd/kpasswd.c
new file mode 100644 (file)
index 0000000..b844628
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden). 
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ *
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the distribution. 
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors 
+ *    may be used to endorse or promote products derived from this software 
+ *    without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#include "kpasswd_locl.h"
+RCSID("$Id: kpasswd.c 19078 2006-11-20 18:12:41Z lha $");
+
+static int version_flag;
+static int help_flag;
+static char *admin_principal_str;
+static char *cred_cache_str;
+
+static struct getargs args[] = {
+    { "admin-principal",       0,   arg_string, &admin_principal_str },
+    { "cache",                 'c', arg_string, &cred_cache_str },
+    { "version",               0,   arg_flag, &version_flag },
+    { "help",                  0,   arg_flag, &help_flag }
+};
+
+static void
+usage (int ret, struct getargs *a, int num_args)
+{
+    arg_printusage (a, num_args, NULL, "[principal ...]");
+    exit (ret);
+}
+
+static int
+change_password(krb5_context context,
+               krb5_principal principal,
+               krb5_ccache id)
+{
+    krb5_data result_code_string, result_string;
+    int result_code;
+    krb5_error_code ret;
+    char pwbuf[BUFSIZ];
+    char *msg, *name;
+
+    krb5_data_zero (&result_code_string);
+    krb5_data_zero (&result_string);
+
+    name = msg = NULL;
+    if (principal == NULL)
+       asprintf(&msg, "New password: ");
+    else {
+       ret = krb5_unparse_name(context, principal, &name);
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_unparse_name");
+
+       asprintf(&msg, "New password for %s: ", name);
+    }
+
+    if (msg == NULL)
+       krb5_errx (context, 1, "out of memory");
+
+    ret = UI_UTIL_read_pw_string (pwbuf, sizeof(pwbuf), msg, 1);
+    free(msg);
+    if (name)
+       free(name);
+    if (ret != 0) {
+       return 1;
+    }
+
+    ret = krb5_set_password_using_ccache (context, id, pwbuf,
+                                         principal,
+                                         &result_code,
+                                         &result_code_string,
+                                         &result_string);
+    if (ret) {
+       krb5_warn (context, ret, "krb5_set_password_using_ccache");
+       return 1;
+    }
+
+    printf ("%s%s%.*s\n", krb5_passwd_result_to_string(context, result_code),
+           result_string.length > 0 ? " : " : "",
+           (int)result_string.length,
+           result_string.length > 0 ? (char *)result_string.data : "");
+
+    krb5_data_free (&result_code_string);
+    krb5_data_free (&result_string);
+
+    return ret != 0;
+}
+
+
+int
+main (int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_principal principal;
+    int optind = 0;
+    krb5_get_init_creds_opt *opt;
+    krb5_ccache id = NULL;
+    int exit_value;
+
+    optind = krb5_program_setup(&context, argc, argv,
+                               args, sizeof(args) / sizeof(args[0]), usage);
+
+    if (help_flag)
+       usage (0, args, sizeof(args) / sizeof(args[0]));
+
+    if(version_flag){
+       print_version (NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    ret = krb5_init_context (&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+  
+    ret = krb5_get_init_creds_opt_alloc (context, &opt);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");
+    
+    krb5_get_init_creds_opt_set_tkt_life (opt, 300);
+    krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
+    krb5_get_init_creds_opt_set_proxiable (opt, FALSE);
+
+    if (cred_cache_str) {
+       ret = krb5_cc_resolve(context, cred_cache_str, &id);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_cc_resolve");
+    } else {
+       ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_cc_gen_new");
+    }
+
+    if (cred_cache_str == NULL) {
+       krb5_principal admin_principal = NULL;
+       krb5_creds cred;
+
+       if (admin_principal_str) {
+           ret = krb5_parse_name (context, admin_principal_str,
+                                  &admin_principal);
+           if (ret)
+               krb5_err (context, 1, ret, "krb5_parse_name");
+       } else if (argc == 1) {
+           ret = krb5_parse_name (context, argv[0], &admin_principal);
+           if (ret)
+               krb5_err (context, 1, ret, "krb5_parse_name");
+       } else {
+           ret = krb5_get_default_principal (context, &admin_principal);
+           if (ret)
+               krb5_err (context, 1, ret, "krb5_get_default_principal");
+       }
+
+       ret = krb5_get_init_creds_password (context,
+                                           &cred,
+                                           admin_principal,
+                                           NULL,
+                                           krb5_prompter_posix,
+                                           NULL,
+                                           0,
+                                           "kadmin/changepw",
+                                           opt);
+       switch (ret) {
+       case 0:
+           break;
+       case KRB5_LIBOS_PWDINTR :
+           return 1;
+       case KRB5KRB_AP_ERR_BAD_INTEGRITY :
+       case KRB5KRB_AP_ERR_MODIFIED :
+           krb5_errx(context, 1, "Password incorrect");
+           break;
+       default:
+           krb5_err(context, 1, ret, "krb5_get_init_creds");
+       }
+       
+       krb5_get_init_creds_opt_free(context, opt);
+       
+       ret = krb5_cc_initialize(context, id, admin_principal);
+       krb5_free_principal(context, admin_principal);
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_cc_initialize");
+
+       ret = krb5_cc_store_cred(context, id, &cred);    
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_cc_store_cred");
+       
+       krb5_free_cred_contents (context, &cred);
+    }
+
+    if (argc == 0) {
+       exit_value = change_password(context, NULL, id);
+    } else {
+       exit_value = 0;
+
+       while (argc-- > 0) {
+
+           ret = krb5_parse_name (context, argv[0], &principal);
+           if (ret)
+               krb5_err (context, 1, ret, "krb5_parse_name");
+
+           ret = change_password(context, principal, id);
+           if (ret)
+               exit_value = 1;
+           krb5_free_principal(context, principal);
+           argv++;
+       }
+    }
+
+    if (cred_cache_str == NULL) {
+       ret = krb5_cc_destroy(context, id);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_cc_destroy");
+    } else {
+       ret = krb5_cc_close(context, id);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_cc_close");
+    }
+
+    krb5_free_context (context);
+    return ret;
+}
diff --git a/source4/heimdal/kpasswd/kpasswd_locl.h b/source4/heimdal/kpasswd/kpasswd_locl.h
new file mode 100644 (file)
index 0000000..b797ceb
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden). 
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ *
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the distribution. 
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors 
+ *    may be used to endorse or promote products derived from this software 
+ *    without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $Id: kpasswd_locl.h 11444 2002-09-10 20:03:49Z joda $ */
+
+#ifndef __KPASSWD_LOCL_H__
+#define __KPASSWD_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#include <err.h>
+#include <roken.h>
+#include <getarg.h>
+#include <krb5.h>
+#include "crypto-headers.h" /* for des_read_pw_string */
+
+#endif /* __KPASSWD_LOCL_H__ */
diff --git a/source4/heimdal/lib/krb5/prog_setup.c b/source4/heimdal/lib/krb5/prog_setup.c
new file mode 100644 (file)
index 0000000..0586155
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden). 
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ *
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the distribution. 
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors 
+ *    may be used to endorse or promote products derived from this software 
+ *    without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#include "krb5_locl.h"
+#include <getarg.h>
+#include <err.h>
+
+RCSID("$Id: prog_setup.c 15470 2005-06-17 04:29:41Z lha $");
+
+void KRB5_LIB_FUNCTION
+krb5_std_usage(int code, struct getargs *args, int num_args)
+{
+    arg_printusage(args, num_args, NULL, "");
+    exit(code);
+}
+
+int KRB5_LIB_FUNCTION
+krb5_program_setup(krb5_context *context, int argc, char **argv,
+                  struct getargs *args, int num_args, 
+                  void (*usage)(int, struct getargs*, int))
+{
+    krb5_error_code ret;
+    int optidx = 0;
+
+    if(usage == NULL)
+       usage = krb5_std_usage;
+
+    setprogname(argv[0]);
+    ret = krb5_init_context(context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+    
+    if(getarg(args, num_args, argc, argv, &optidx))
+       (*usage)(1, args, num_args);
+    return optidx;
+}
diff --git a/source4/heimdal/lib/roken/rkpty.c b/source4/heimdal/lib/roken/rkpty.c
new file mode 100644 (file)
index 0000000..e29b2c5
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2008 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#ifndef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef HAVE_PTY_H
+#include <pty.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+
+#include "roken.h"
+#include <getarg.h>
+
+struct command {
+    enum { CMD_EXPECT = 0, CMD_SEND, CMD_PASSWORD } type;
+    unsigned int lineno;
+    char *str;
+    struct command *next;
+};
+
+/*
+ *
+ */
+
+static struct command *commands, **next = &commands;
+
+static sig_atomic_t alarmset = 0;
+
+static int timeout = 10;
+static int verbose;
+static int help_flag;
+static int version_flag;
+
+static int master;
+static int slave;
+static char line[256] = { 0 };
+
+static void
+caught_signal(int signo)
+{
+    alarmset = signo;
+}
+
+
+static void
+open_pty(void)
+{
+#if defined(HAVE_OPENPTY) || defined(__linux) || defined(__osf__) /* XXX */
+    if(openpty(&master, &slave, line, 0, 0) == 0)
+       return;
+#endif /* HAVE_OPENPTY .... */
+    /* more cases, like open /dev/ptmx, etc */
+
+    exit(77);
+}
+
+/*
+ *
+ */
+
+static char *
+iscmd(const char *buf, const char *s)
+{
+    size_t len = strlen(s);
+    if (strncmp(buf, s, len) != 0)
+       return NULL;
+    return estrdup(buf + len);
+}
+
+static void
+parse_configuration(const char *fn)
+{
+    struct command *c;
+    char s[1024];
+    char *str;
+    unsigned int lineno = 0;
+    FILE *cmd;
+
+    cmd = fopen(fn, "r");
+    if (cmd == NULL)
+       err(1, "open: %s", fn);
+
+    while (fgets(s, sizeof(s),  cmd) != NULL) {
+
+       s[strcspn(s, "#\n")] = '\0';
+       lineno++;
+
+       c = calloc(1, sizeof(*c));
+       if (c == NULL)
+           errx(1, "malloc");
+
+       c->lineno = lineno;
+       (*next) = c;
+       next = &(c->next);
+
+       if ((str = iscmd(s, "expect ")) != NULL) {
+           c->type = CMD_EXPECT;
+           c->str = str;
+       } else if ((str = iscmd(s, "send ")) != NULL) {
+           c->type = CMD_SEND;
+           c->str = str;
+       } else if ((str = iscmd(s, "password ")) != NULL) {
+           c->type = CMD_PASSWORD;
+           c->str = str;
+       } else
+           errx(1, "Invalid command on line %d: %s", lineno, s);
+    }
+
+    fclose(cmd);
+}
+
+
+/*
+ *
+ */
+
+static int
+eval_parent(pid_t pid)
+{
+    struct command *c;
+    char in;
+    size_t len = 0;
+    ssize_t sret;
+
+    for (c = commands; c != NULL; c = c->next) {
+       switch(c->type) {
+       case CMD_EXPECT:
+           if (verbose)
+               printf("[expecting %s]", c->str);
+           len = 0;
+           alarm(timeout);
+           while((sret = read(master, &in, sizeof(in))) > 0) {
+               alarm(timeout);
+               printf("%c", in);
+               if (c->str[len] != in) {
+                   len = 0;
+                   continue;
+               }
+               len++;
+               if (c->str[len] == '\0')
+                   break;
+           }
+           alarm(0);
+           if (alarmset == SIGALRM)
+               errx(1, "timeout waiting for %s (line %u)", 
+                    c->str, c->lineno);
+           else if (alarmset)
+               errx(1, "got a signal %d waiting for %s (line %u)", 
+                    alarmset, c->str, c->lineno);
+           if (sret <= 0)
+               errx(1, "end command while waiting for %s (line %u)",
+                    c->str, c->lineno);
+           break;
+       case CMD_SEND:
+       case CMD_PASSWORD: {
+           size_t i = 0;
+           const char *msg = (c->type == CMD_PASSWORD) ? "****" : c->str;
+
+           if (verbose)
+               printf("[send %s]", msg);
+
+           len = strlen(c->str);
+
+           while (i < len) {
+               if (c->str[i] == '\\' && i < len - 1) {
+                   char ctrl;
+                   i++;
+                   switch(c->str[i]) {
+                   case 'n': ctrl = '\n'; break;
+                   case 'r': ctrl = '\r'; break;
+                   case 't': ctrl = '\t'; break;
+                   default:
+                       errx(1, "unknown control char %c (line %u)", 
+                            c->str[i], c->lineno);
+                   }
+                   if (net_write(master, &ctrl, 1) != 1)
+                       errx(1, "command refused input (line %u)", c->lineno);
+               } else {
+                   if (net_write(master, &c->str[i], 1) != 1)
+                       errx(1, "command refused input (line %u)", c->lineno);
+               }
+               i++;
+           }
+           break;
+       }
+       default:
+           abort();
+       }
+    }
+    while(read(master, &in, sizeof(in)) > 0)
+       printf("%c", in);
+
+    if (verbose)
+       printf("[end of program]\n");
+
+    /*
+     * Fetch status from child
+     */
+    {
+       int ret, status;
+
+       ret = waitpid(pid, &status, 0);
+       if (ret == -1)
+           err(1, "waitpid");
+       if (WIFEXITED(status) && WEXITSTATUS(status))
+           return WEXITSTATUS(status);
+       else if (WIFSIGNALED(status)) {
+           printf("killed by signal: %d\n", WTERMSIG(status));
+           return 1;
+       }
+    }
+    return 0;
+}
+
+/*
+ *
+ */
+
+static struct getargs args[] = {
+    { "timeout",       't', arg_integer, &timeout, "timout", "seconds" },
+    { "verbose",       'v', arg_counter, &verbose, "verbose debugging" },
+    { "version",       0, arg_flag,    &version_flag, "print version" },
+    { "help",          0, arg_flag,    &help_flag, NULL }
+};
+
+static void
+usage(int ret)
+{
+    arg_printusage (args, sizeof(args)/sizeof(*args), NULL, "infile command..");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    int optidx = 0;
+    pid_t pid;
+
+    setprogname(argv[0]);
+
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
+       usage(1);
+
+    if (help_flag)
+       usage (0);
+
+    if (version_flag) {
+       fprintf (stderr, "%s from %s-%s\n", getprogname(), PACKAGE, VERSION);
+       return 0;
+    }
+
+    argv += optidx;
+    argc -= optidx;
+
+    if (argc < 2)
+       usage(1);
+
+    parse_configuration(argv[0]);
+
+    argv += 1;
+    argc -= 1;
+
+    open_pty();
+
+    pid = fork();
+    switch (pid) {
+    case -1:
+       err(1, "Failed to fork");
+    case 0:
+
+       if(setsid()<0)
+           err(1, "setsid");
+
+       dup2(slave, STDIN_FILENO);
+       dup2(slave, STDOUT_FILENO);
+       dup2(slave, STDERR_FILENO);
+       closefrom(STDERR_FILENO + 1);
+
+       execvp(argv[0], argv); /* add NULL to end of array ? */
+       err(1, "Failed to exec: %s", argv[0]);
+    default:
+       close(slave);
+       {
+           struct sigaction sa;
+
+           sa.sa_handler = caught_signal;
+           sa.sa_flags = 0;
+           sigemptyset (&sa.sa_mask);
+           
+           sigaction(SIGALRM, &sa, NULL);
+       }
+
+       return eval_parent(pid);
+    }
+}
index 038c4d9417200d505343806361c74d9fa558b273..06e798ce2750977466dab8705ce1c30ef487176e 100644 (file)
@@ -49,6 +49,7 @@ AC_CHECK_HEADERS([                            \
        errno.h                                 \
        inttypes.h                              \
        netdb.h                                 \
+       pty.h                                   \
        signal.h                                \
        sys/bswap.h                             \
        sys/file.h                              \
@@ -158,6 +159,13 @@ m4_include(heimdal/cf/find-func-no-libs.m4)
 m4_include(heimdal/cf/find-func-no-libs2.m4)
 m4_include(heimdal/cf/resolv.m4)
 
+
+AC_CHECK_LIB_EXT(util, OPENPTY_LIBS, openpty)
+
+SMB_ENABLE(OPENPTY,YES)
+
+SMB_EXT_LIB(OPENPTY,[${OPENPTY_LIBS}],[${OPENPTY_CFLAGS}],[${OPENPTY_CPPFLAGS}],[${OPENPTY_LDFLAGS}])
+
 smb_save_LIBS=$LIBS
 RESOLV_LIBS=""
 LIBS=""
index 67fda9dd58a76250e318217d64a773bf133886fc..7b1c9f515336a8c27922ddfa0a2e0582c76bdddb 100644 (file)
@@ -322,6 +322,7 @@ HEIMDAL_KRB5_OBJ_FILES = \
        $(heimdalsrcdir)/lib/krb5/pkinit.o \
        $(heimdalsrcdir)/lib/krb5/plugin.o \
        $(heimdalsrcdir)/lib/krb5/principal.o \
+       $(heimdalsrcdir)/lib/krb5/prog_setup.o \
        $(heimdalsrcdir)/lib/krb5/pac.o \
        $(heimdalsrcdir)/lib/krb5/prompter_posix.o \
        $(heimdalsrcdir)/lib/krb5/rd_cred.o \
@@ -600,6 +601,7 @@ HEIMDAL_ROKEN_OBJ_FILES = \
        $(heimdalsrcdir)/lib/roken/dumpdata.o \
        $(heimdalsrcdir)/lib/roken/emalloc.o \
        $(heimdalsrcdir)/lib/roken/ecalloc.o \
+       $(heimdalsrcdir)/lib/roken/getarg.o \
        $(heimdalsrcdir)/lib/roken/get_window_size.o \
        $(heimdalsrcdir)/lib/roken/h_errno.o \
        $(heimdalsrcdir)/lib/roken/issuid.o \
@@ -612,6 +614,7 @@ HEIMDAL_ROKEN_OBJ_FILES = \
        $(heimdalsrcdir)/lib/roken/roken_gethostby.o \
        $(heimdalsrcdir)/lib/roken/signal.o \
        $(heimdalsrcdir)/lib/roken/vis.o \
+       $(heimdalsrcdir)/lib/roken/setprogname.o \
        $(heimdalsrcdir)/lib/roken/strlwr.o \
        $(heimdalsrcdir)/lib/roken/strsep_copy.o \
        $(heimdalsrcdir)/lib/roken/strsep.o \
@@ -677,8 +680,6 @@ dist:: $(heimdalsrcdir)/lib/asn1/lex.c
 asn1_compile_OBJ_FILES = \
        $(asn1_compile_ASN1_OBJ_FILES) \
        $(heimdalsrcdir)/lib/roken/emalloc.ho \
-       $(heimdalsrcdir)/lib/roken/getarg.ho \
-       $(heimdalsrcdir)/lib/roken/setprogname.ho \
        $(heimdalsrcdir)/lib/roken/strupr.ho \
        $(heimdalsrcdir)/lib/roken/get_window_size.ho \
        $(heimdalsrcdir)/lib/roken/estrdup.ho \
@@ -713,10 +714,8 @@ compile_et_OBJ_FILES = $(heimdalsrcdir)/lib/vers/print_version.ho \
        $(heimdalsrcdir)/lib/com_err/parse.ho \
        $(heimdalsrcdir)/lib/com_err/lex.ho \
        $(heimdalsrcdir)/lib/com_err/compile_et.ho \
-       $(heimdalsrcdir)/lib/roken/getarg.ho \
        $(heimdalsrcdir)/lib/roken/get_window_size.ho \
        $(heimdalsrcdir)/lib/roken/strupr.ho \
-       $(heimdalsrcdir)/lib/roken/setprogname.ho \
        $(socketwrappersrcdir)/socket_wrapper.ho \
        $(heimdalbuildsrcdir)/replace.ho
 
@@ -761,8 +760,30 @@ PRIVATE_DEPENDENCIES = HEIMDAL_KRB5 HEIMDAL_NTLM
 #######################
 
 samba4kinit_OBJ_FILES = $(heimdalsrcdir)/kuser/kinit.o \
-       $(heimdalsrcdir)/lib/vers/print_version.o \
-       $(heimdalsrcdir)/lib/roken/setprogname.o \
-       $(heimdalsrcdir)/lib/roken/getarg.o 
+       $(heimdalsrcdir)/lib/vers/print_version.o 
 
 $(samba4kinit_OBJ_FILES): CFLAGS+=-I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/roken
+
+#######################
+# Start BINARY compile_et
+[BINARY::samba4kpasswd]
+PRIVATE_DEPENDENCIES = HEIMDAL_KRB5 HEIMDAL_NTLM
+# End BINARY compile_et
+#######################
+
+samba4kpasswd_OBJ_FILES = $(heimdalsrcdir)/kpasswd/kpasswd.o \
+       $(heimdalsrcdir)/lib/vers/print_version.o 
+
+$(samba4kpasswd_OBJ_FILES): CFLAGS+=-I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/roken
+
+#######################
+# Start BINARY compile_et
+[BINARY::rkpty]
+PRIVATE_DEPENDENCIES = HEIMDAL_ROKEN OPENPTY
+# End BINARY compile_et
+#######################
+
+rkpty_OBJ_FILES = $(heimdalsrcdir)/lib/roken/rkpty.o \
+       $(socketwrappersrcdir)/socket_wrapper.o
+
+$(rkpty_OBJ_FILES): CFLAGS+=-I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/roken -DPACKAGE=\"Samba\"