Home | History | Annotate | Line # | Download | only in kpasswd
      1 /*	$NetBSD: kpasswd-generator.c,v 1.2 2017/01/28 21:31:45 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2000 - 2004 Kungliga Tekniska Hgskolan
      5  * (Royal Institute of Technology, Stockholm, Sweden).
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * 3. Neither the name of the Institute nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include "kpasswd_locl.h"
     37 
     38 __RCSID("$NetBSD: kpasswd-generator.c,v 1.2 2017/01/28 21:31:45 christos Exp $");
     39 
     40 static unsigned
     41 read_words(const char *filename, char ***ret_w)
     42 {
     43     unsigned n, alloc;
     44     FILE *f;
     45     char buf[256];
     46     char **w = NULL;
     47 
     48     f = fopen(filename, "r");
     49     if (f == NULL)
     50 	err(1, "cannot open %s", filename);
     51     alloc = n = 0;
     52     while (fgets(buf, sizeof(buf), f) != NULL) {
     53 	buf[strcspn(buf, "\r\n")] = '\0';
     54 	if (n >= alloc) {
     55 	    alloc += 16;
     56 	    w = erealloc(w, alloc * sizeof(char *));
     57 	}
     58 	w[n++] = estrdup(buf);
     59     }
     60     *ret_w = w;
     61     if (n == 0)
     62 	errx(1, "%s is an empty file, no words to try", filename);
     63     fclose(f);
     64     return n;
     65 }
     66 
     67 static int
     68 nop_prompter(krb5_context context,
     69 	     void *data,
     70 	     const char *name,
     71 	     const char *banner,
     72 	     int num_prompts,
     73 	     krb5_prompt prompts[])
     74 {
     75     return 0;
     76 }
     77 
     78 static void
     79 generate_requests(const char *filename, unsigned nreq)
     80 {
     81     krb5_context context;
     82     krb5_error_code ret;
     83     int i;
     84     char **words;
     85     unsigned nwords, k;
     86 
     87     ret = krb5_init_context(&context);
     88     if (ret)
     89 	errx (1, "krb5_init_context failed: %d", ret);
     90 
     91     nwords = read_words(filename, &words);
     92 
     93     for (i = 0; i < nreq; ++i) {
     94 	char *name = words[rand() % nwords];
     95 	krb5_get_init_creds_opt *opt;
     96 	krb5_creds cred;
     97 	krb5_principal principal;
     98 	int result_code;
     99 	krb5_data result_code_string, result_string;
    100 	char *old_pwd, *new_pwd;
    101 	int aret;
    102 
    103 	krb5_get_init_creds_opt_alloc(context, &opt);
    104 	krb5_get_init_creds_opt_set_tkt_life (opt, 300);
    105 	krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
    106 	krb5_get_init_creds_opt_set_proxiable (opt, FALSE);
    107 
    108 	ret = krb5_parse_name(context, name, &principal);
    109 	if (ret)
    110 	    krb5_err(context, 1, ret, "krb5_parse_name %s", name);
    111 
    112 	aret = asprintf(&old_pwd, "%s", name);
    113 	if (aret == -1)
    114 	    krb5_errx(context, 1, "out of memory");
    115 	aret = asprintf(&new_pwd, "%s2", name);
    116 	if (aret == -1)
    117 	    krb5_errx(context, 1, "out of memory");
    118 
    119 	ret = krb5_get_init_creds_password(context,
    120 					   &cred,
    121 					   principal,
    122 					   old_pwd,
    123 					   nop_prompter,
    124 					   NULL,
    125 					   0,
    126 					   "kadmin/changepw",
    127 					   opt);
    128 	if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY
    129 	    || ret == KRB5KRB_AP_ERR_MODIFIED) {
    130 	    char *tmp;
    131 
    132 	    tmp = new_pwd;
    133 	    new_pwd = old_pwd;
    134 	    old_pwd = tmp;
    135 
    136             ret = krb5_get_init_creds_password(context,
    137                                                &cred,
    138                                                principal,
    139                                                old_pwd,
    140                                                nop_prompter,
    141                                                NULL,
    142                                                0,
    143                                                "kadmin/changepw",
    144                                                opt);
    145 	}
    146 	if (ret)
    147 	    krb5_err(context, 1, ret, "krb5_get_init_creds_password");
    148 
    149 	krb5_free_principal(context, principal);
    150 
    151 
    152         ret = krb5_set_password(context,
    153                                 &cred,
    154                                 new_pwd,
    155                                 NULL,
    156                                 &result_code,
    157                                 &result_code_string,
    158                                 &result_string);
    159 	if (ret)
    160 	    krb5_err(context, 1, ret, "krb5_change_password");
    161 
    162 	free(old_pwd);
    163 	free(new_pwd);
    164 	krb5_free_cred_contents(context, &cred);
    165 	krb5_get_init_creds_opt_free(context, opt);
    166     }
    167 
    168     for (k = 0; k < nwords; k++)
    169         free(words[k]);
    170     free(words);
    171 }
    172 
    173 static int version_flag	= 0;
    174 static int help_flag	= 0;
    175 
    176 static struct getargs args[] = {
    177     { "version", 	0,   arg_flag, &version_flag, NULL, NULL },
    178     { "help",		0,   arg_flag, &help_flag,    NULL, NULL }
    179 };
    180 
    181 static void
    182 usage(int ret)
    183 {
    184     arg_printusage(args,
    185 		   sizeof(args)/sizeof(*args),
    186 		   NULL,
    187 		   "file [number]");
    188     exit (ret);
    189 }
    190 
    191 int
    192 main(int argc, char **argv)
    193 {
    194     int optidx = 0;
    195     int nreq;
    196     char *end;
    197 
    198     setprogname(argv[0]);
    199     if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
    200 	usage(1);
    201     if (help_flag)
    202 	usage (0);
    203     if (version_flag) {
    204 	print_version(NULL);
    205 	return 0;
    206     }
    207     argc -= optidx;
    208     argv += optidx;
    209 
    210     if (argc != 2)
    211 	usage (1);
    212     srand (0);
    213     nreq = strtol(argv[1], &end, 0);
    214     if (argv[1] == end || *end != '\0')
    215 	usage (1);
    216     generate_requests(argv[0], nreq);
    217     return 0;
    218 }
    219