172445Sassar/*
2233294Sstas * Copyright (c) 2000 - 2004 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
572445Sassar *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
972445Sassar *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
1272445Sassar *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
1672445Sassar *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
2072445Sassar *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
3272445Sassar */
3372445Sassar
3472445Sassar#include "kpasswd_locl.h"
3572445Sassar
36233294SstasRCSID("$Id$");
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);
61233294Sstas    fclose(f);
6272445Sassar    return n;
6372445Sassar}
6472445Sassar
6572445Sassarstatic int
6672445Sassarnop_prompter (krb5_context context,
6772445Sassar	      void *data,
6878527Sassar	      const char *name,
6972445Sassar	      const char *banner,
7072445Sassar	      int num_prompts,
7172445Sassar	      krb5_prompt prompts[])
7272445Sassar{
7372445Sassar    return 0;
7472445Sassar}
7572445Sassar
7672445Sassarstatic void
7772445Sassargenerate_requests (const char *filename, unsigned nreq)
7872445Sassar{
7972445Sassar    krb5_context context;
8072445Sassar    krb5_error_code ret;
8172445Sassar    int i;
8272445Sassar    char **words;
8372445Sassar    unsigned nwords;
8472445Sassar
8572445Sassar    ret = krb5_init_context (&context);
8672445Sassar    if (ret)
8772445Sassar	errx (1, "krb5_init_context failed: %d", ret);
8872445Sassar
8972445Sassar    nwords = read_words (filename, &words);
9072445Sassar
9172445Sassar    for (i = 0; i < nreq; ++i) {
9272445Sassar	char *name = words[rand() % nwords];
93178825Sdfr	krb5_get_init_creds_opt *opt;
9472445Sassar	krb5_creds cred;
9572445Sassar	krb5_principal principal;
9672445Sassar	int result_code;
9772445Sassar	krb5_data result_code_string, result_string;
9872445Sassar	char *old_pwd, *new_pwd;
9972445Sassar
100178825Sdfr	krb5_get_init_creds_opt_alloc (context, &opt);
101178825Sdfr	krb5_get_init_creds_opt_set_tkt_life (opt, 300);
102178825Sdfr	krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
103178825Sdfr	krb5_get_init_creds_opt_set_proxiable (opt, FALSE);
10472445Sassar
10572445Sassar	ret = krb5_parse_name (context, name, &principal);
10672445Sassar	if (ret)
10772445Sassar	    krb5_err (context, 1, ret, "krb5_parse_name %s", name);
10872445Sassar
10972445Sassar	asprintf (&old_pwd, "%s", name);
11072445Sassar	asprintf (&new_pwd, "%s2", name);
11172445Sassar
11272445Sassar	ret = krb5_get_init_creds_password (context,
11372445Sassar					    &cred,
11472445Sassar					    principal,
11572445Sassar					    old_pwd,
11672445Sassar					    nop_prompter,
11772445Sassar					    NULL,
11872445Sassar					    0,
11972445Sassar					    "kadmin/changepw",
120178825Sdfr					    opt);
12172445Sassar	if( ret == KRB5KRB_AP_ERR_BAD_INTEGRITY
12272445Sassar	    || ret == KRB5KRB_AP_ERR_MODIFIED) {
12372445Sassar	    char *tmp;
12472445Sassar
12572445Sassar	    tmp = new_pwd;
12672445Sassar	    new_pwd = old_pwd;
12772445Sassar	    old_pwd = tmp;
12872445Sassar
12972445Sassar	    ret = krb5_get_init_creds_password (context,
13072445Sassar						&cred,
13172445Sassar						principal,
13272445Sassar						old_pwd,
13372445Sassar						nop_prompter,
13472445Sassar						NULL,
13572445Sassar						0,
13672445Sassar						"kadmin/changepw",
137178825Sdfr						opt);
13872445Sassar	}
13972445Sassar	if (ret)
14072445Sassar	    krb5_err (context, 1, ret, "krb5_get_init_creds_password");
14172445Sassar
14272445Sassar	krb5_free_principal (context, principal);
14372445Sassar
144233294Sstas
145233294Sstas	ret = krb5_set_password (context,
146233294Sstas				 &cred,
147233294Sstas				 new_pwd,
148233294Sstas				 NULL,
149233294Sstas				 &result_code,
150233294Sstas				 &result_code_string,
151233294Sstas				 &result_string);
15272445Sassar	if (ret)
15372445Sassar	    krb5_err (context, 1, ret, "krb5_change_password");
15472445Sassar
15572445Sassar	free (old_pwd);
15672445Sassar	free (new_pwd);
157178825Sdfr	krb5_free_cred_contents (context, &cred);
158178825Sdfr	krb5_get_init_creds_opt_free(context, opt);
15972445Sassar    }
16072445Sassar}
16172445Sassar
16272445Sassarstatic int version_flag	= 0;
16372445Sassarstatic int help_flag	= 0;
16472445Sassar
16572445Sassarstatic struct getargs args[] = {
16672445Sassar    { "version", 	0,   arg_flag, &version_flag },
16772445Sassar    { "help",		0,   arg_flag, &help_flag }
16872445Sassar};
16972445Sassar
17072445Sassarstatic void
17172445Sassarusage (int ret)
17272445Sassar{
17372445Sassar    arg_printusage (args,
17472445Sassar		    sizeof(args)/sizeof(*args),
17572445Sassar		    NULL,
17672445Sassar		    "file [number]");
17772445Sassar    exit (ret);
17872445Sassar}
17972445Sassar
18072445Sassarint
18172445Sassarmain(int argc, char **argv)
18272445Sassar{
18372445Sassar    int optind = 0;
18472445Sassar    int nreq;
18572445Sassar    char *end;
18672445Sassar
18778527Sassar    setprogname(argv[0]);
18872445Sassar    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
18972445Sassar	usage(1);
19090926Snectar    if (help_flag)
19190926Snectar	usage (0);
19290926Snectar    if (version_flag) {
19390926Snectar	print_version(NULL);
19490926Snectar	return 0;
19590926Snectar    }
19672445Sassar    argc -= optind;
19772445Sassar    argv += optind;
19872445Sassar
19972445Sassar    if (argc != 2)
20072445Sassar	usage (1);
20172445Sassar    srand (0);
20272445Sassar    nreq = strtol (argv[1], &end, 0);
20372445Sassar    if (argv[1] == end || *end != '\0')
20472445Sassar	usage (1);
20572445Sassar    generate_requests (argv[0], nreq);
20672445Sassar    return 0;
20772445Sassar}
208