172445Sassar/*
2178825Sdfr * Copyright (c) 2000 - 2004 Kungliga Tekniska H�gskolan
372445Sassar * (Royal Institute of Technology, Stockholm, Sweden).
472445Sassar * All rights reserved.
572445Sassar *
672445Sassar * Redistribution and use in source and binary forms, with or without
772445Sassar * modification, are permitted provided that the following conditions
872445Sassar * are met:
972445Sassar *
1072445Sassar * 1. Redistributions of source code must retain the above copyright
1172445Sassar *    notice, this list of conditions and the following disclaimer.
1272445Sassar *
1372445Sassar * 2. Redistributions in binary form must reproduce the above copyright
1472445Sassar *    notice, this list of conditions and the following disclaimer in the
1572445Sassar *    documentation and/or other materials provided with the distribution.
1672445Sassar *
1772445Sassar * 3. Neither the name of the Institute nor the names of its contributors
1872445Sassar *    may be used to endorse or promote products derived from this software
1972445Sassar *    without specific prior written permission.
2072445Sassar *
2172445Sassar * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2272445Sassar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2372445Sassar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2472445Sassar * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2572445Sassar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2672445Sassar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2772445Sassar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2872445Sassar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2972445Sassar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3072445Sassar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3172445Sassar * SUCH DAMAGE.
3272445Sassar */
3372445Sassar
3472445Sassar#include "kpasswd_locl.h"
3572445Sassar
36178825SdfrRCSID("$Id: kpasswd-generator.c 19233 2006-12-06 08:04:05Z lha $");
3772445Sassar
3872445Sassarstatic unsigned
3972445Sassarread_words (const char *filename, char ***ret_w)
4072445Sassar{
4172445Sassar    unsigned n, alloc;
4272445Sassar    FILE *f;
4372445Sassar    char buf[256];
4472445Sassar    char **w = NULL;
4572445Sassar
4672445Sassar    f = fopen (filename, "r");
4772445Sassar    if (f == NULL)
4872445Sassar	err (1, "cannot open %s", filename);
4972445Sassar    alloc = n = 0;
5072445Sassar    while (fgets (buf, sizeof(buf), f) != NULL) {
51178825Sdfr	buf[strcspn(buf, "\r\n")] = '\0';
5272445Sassar	if (n >= alloc) {
5372445Sassar	    alloc += 16;
5472445Sassar	    w = erealloc (w, alloc * sizeof(char **));
5572445Sassar	}
5672445Sassar	w[n++] = estrdup (buf);
5772445Sassar    }
5872445Sassar    *ret_w = w;
59178825Sdfr    if (n == 0)
60178825Sdfr	errx(1, "%s is an empty file, no words to try", filename);
6172445Sassar    return n;
6272445Sassar}
6372445Sassar
6472445Sassarstatic int
6572445Sassarnop_prompter (krb5_context context,
6672445Sassar	      void *data,
6778527Sassar	      const char *name,
6872445Sassar	      const char *banner,
6972445Sassar	      int num_prompts,
7072445Sassar	      krb5_prompt prompts[])
7172445Sassar{
7272445Sassar    return 0;
7372445Sassar}
7472445Sassar
7572445Sassarstatic void
7672445Sassargenerate_requests (const char *filename, unsigned nreq)
7772445Sassar{
7872445Sassar    krb5_context context;
7972445Sassar    krb5_error_code ret;
8072445Sassar    int i;
8172445Sassar    char **words;
8272445Sassar    unsigned nwords;
8372445Sassar
8472445Sassar    ret = krb5_init_context (&context);
8572445Sassar    if (ret)
8672445Sassar	errx (1, "krb5_init_context failed: %d", ret);
8772445Sassar
8872445Sassar    nwords = read_words (filename, &words);
8972445Sassar
9072445Sassar    for (i = 0; i < nreq; ++i) {
9172445Sassar	char *name = words[rand() % nwords];
92178825Sdfr	krb5_get_init_creds_opt *opt;
9372445Sassar	krb5_creds cred;
9472445Sassar	krb5_principal principal;
9572445Sassar	int result_code;
9672445Sassar	krb5_data result_code_string, result_string;
9772445Sassar	char *old_pwd, *new_pwd;
9872445Sassar
99178825Sdfr	krb5_get_init_creds_opt_alloc (context, &opt);
100178825Sdfr	krb5_get_init_creds_opt_set_tkt_life (opt, 300);
101178825Sdfr	krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
102178825Sdfr	krb5_get_init_creds_opt_set_proxiable (opt, FALSE);
10372445Sassar
10472445Sassar	ret = krb5_parse_name (context, name, &principal);
10572445Sassar	if (ret)
10672445Sassar	    krb5_err (context, 1, ret, "krb5_parse_name %s", name);
10772445Sassar
10872445Sassar	asprintf (&old_pwd, "%s", name);
10972445Sassar	asprintf (&new_pwd, "%s2", name);
11072445Sassar
11172445Sassar	ret = krb5_get_init_creds_password (context,
11272445Sassar					    &cred,
11372445Sassar					    principal,
11472445Sassar					    old_pwd,
11572445Sassar					    nop_prompter,
11672445Sassar					    NULL,
11772445Sassar					    0,
11872445Sassar					    "kadmin/changepw",
119178825Sdfr					    opt);
12072445Sassar	if( ret == KRB5KRB_AP_ERR_BAD_INTEGRITY
12172445Sassar	    || ret == KRB5KRB_AP_ERR_MODIFIED) {
12272445Sassar	    char *tmp;
12372445Sassar
12472445Sassar	    tmp = new_pwd;
12572445Sassar	    new_pwd = old_pwd;
12672445Sassar	    old_pwd = tmp;
12772445Sassar
12872445Sassar	    ret = krb5_get_init_creds_password (context,
12972445Sassar						&cred,
13072445Sassar						principal,
13172445Sassar						old_pwd,
13272445Sassar						nop_prompter,
13372445Sassar						NULL,
13472445Sassar						0,
13572445Sassar						"kadmin/changepw",
136178825Sdfr						opt);
13772445Sassar	}
13872445Sassar	if (ret)
13972445Sassar	    krb5_err (context, 1, ret, "krb5_get_init_creds_password");
14072445Sassar
14172445Sassar	krb5_free_principal (context, principal);
14272445Sassar
14372445Sassar	ret = krb5_change_password (context, &cred, new_pwd,
14472445Sassar				    &result_code,
14572445Sassar				    &result_code_string,
14672445Sassar				    &result_string);
14772445Sassar	if (ret)
14872445Sassar	    krb5_err (context, 1, ret, "krb5_change_password");
14972445Sassar
15072445Sassar	free (old_pwd);
15172445Sassar	free (new_pwd);
152178825Sdfr	krb5_free_cred_contents (context, &cred);
153178825Sdfr	krb5_get_init_creds_opt_free(context, opt);
15472445Sassar    }
15572445Sassar}
15672445Sassar
15772445Sassarstatic int version_flag	= 0;
15872445Sassarstatic int help_flag	= 0;
15972445Sassar
16072445Sassarstatic struct getargs args[] = {
16172445Sassar    { "version", 	0,   arg_flag, &version_flag },
16272445Sassar    { "help",		0,   arg_flag, &help_flag }
16372445Sassar};
16472445Sassar
16572445Sassarstatic void
16672445Sassarusage (int ret)
16772445Sassar{
16872445Sassar    arg_printusage (args,
16972445Sassar		    sizeof(args)/sizeof(*args),
17072445Sassar		    NULL,
17172445Sassar		    "file [number]");
17272445Sassar    exit (ret);
17372445Sassar}
17472445Sassar
17572445Sassarint
17672445Sassarmain(int argc, char **argv)
17772445Sassar{
17872445Sassar    int optind = 0;
17972445Sassar    int nreq;
18072445Sassar    char *end;
18172445Sassar
18278527Sassar    setprogname(argv[0]);
18372445Sassar    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
18472445Sassar	usage(1);
18590926Snectar    if (help_flag)
18690926Snectar	usage (0);
18790926Snectar    if (version_flag) {
18890926Snectar	print_version(NULL);
18990926Snectar	return 0;
19090926Snectar    }
19172445Sassar    argc -= optind;
19272445Sassar    argv += optind;
19372445Sassar
19472445Sassar    if (argc != 2)
19572445Sassar	usage (1);
19672445Sassar    srand (0);
19772445Sassar    nreq = strtol (argv[1], &end, 0);
19872445Sassar    if (argv[1] == end || *end != '\0')
19972445Sassar	usage (1);
20072445Sassar    generate_requests (argv[0], nreq);
20172445Sassar    return 0;
20272445Sassar}
203