2 * Copyright (c) 1997 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Kungliga Tekniska
20 * Högskolan and its contributors.
22 * 4. Neither the name of the Institute nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 #define Principal Principal4
48 int open_socket(const char *hostname
)
52 struct sockaddr_in sin
;
53 s
= socket(AF_INET
, SOCK_STREAM
, 0);
58 hp
= gethostbyname(hostname
);
60 warnx("%s: %s", hostname
, hstrerror(h_errno
));
64 memset(&sin
, 0, sizeof(sin
));
65 sin
.sin_family
= AF_INET
;
66 sin
.sin_port
= krb5_getportbyname ("hprop", "tcp", htons(HPROP_PORT
));
67 memcpy(&sin
.sin_addr
, hp
->h_addr
, hp
->h_length
);
68 if(connect(s
, (struct sockaddr
*)&sin
, sizeof(sin
)) < 0){
78 krb5_auth_context auth_context
;
82 int hdb_entry2value(krb5_context
, hdb_entry
*, krb5_data
*);
85 func(krb5_context context
, HDB
*db
, hdb_entry
*entry
, void *appdata
)
88 struct prop_data
*pd
= appdata
;
91 ret
= hdb_entry2value(context
, entry
, &data
);
94 ret
= send_priv(context
, pd
->auth_context
, &data
, pd
->sock
);
95 krb5_data_free(&data
);
100 static des_cblock mkey
;
101 static des_key_schedule msched
;
102 static char realm
[REALM_SZ
];
105 conv_db(void *arg
, Principal
*p
)
107 struct prop_data
*pd
= arg
;
111 memset(&ent
, 0, sizeof(ent
));
113 ret
= krb5_425_conv_principal(pd
->context
, p
->name
, p
->instance
, realm
,
116 krb5_warn(pd
->context
, ret
, "%s.%s@%s", p
->name
, p
->instance
, realm
);
122 ent
.keys
.val
[0].mkvno
= p
->kdc_key_ver
;
123 ent
.keys
.val
[0].salt
= calloc(1, sizeof(*ent
.keys
.val
[0].salt
));
124 ent
.kvno
= p
->key_version
;
125 ent
.keys
.val
[0].key
.keytype
= KEYTYPE_DES
;
126 krb5_data_alloc(&ent
.keys
.val
[0].key
.keyvalue
, sizeof(des_cblock
));
129 unsigned char *key
= ent
.keys
.val
[0].key
.keyvalue
.data
;
130 memcpy(key
, &p
->key_low
, 4);
131 memcpy(key
+ 4, &p
->key_high
, 4);
132 kdb_encrypt_key(key
, key
, &mkey
, msched
, 0);
134 hdb_seal_key(&ent
.keys
.val
[0], msched
);
137 *ent
.max_life
= krb_life_to_time(0, p
->max_life
);
138 if(*ent
.max_life
== (1U << 31) - 1){
144 *ent
.pw_end
= p
->exp_date
;
145 ret
= krb5_make_principal(pd
->context
, &ent
.created_by
.principal
,
150 ent
.created_by
.time
= time(NULL
);
151 ALLOC(ent
.modified_by
);
152 krb5_425_conv_principal(pd
->context
, p
->mod_name
, p
->mod_instance
, realm
,
153 &ent
.modified_by
->principal
);
154 ent
.modified_by
->time
= p
->mod_date
;
156 ent
.flags
.forwardable
= 1;
157 ent
.flags
.renewable
= 1;
158 ent
.flags
.proxiable
= 1;
159 ent
.flags
.postdate
= 1;
160 ent
.flags
.client
= 1;
161 ent
.flags
.server
= 1;
165 ret
= hdb_entry2value(pd
->context
, &ent
, &data
);
168 ret
= send_priv(pd
->context
, pd
->auth_context
, &data
, pd
->sock
);
169 krb5_data_free(&data
);
176 static getarg_strings slaves
;
177 static int version_flag
;
178 static int help_flag
;
179 static char *ktname
= HPROP_KEYTAB
;
180 static char *database
;
185 struct getargs args
[] = {
187 { "slave", 's', arg_strings
, &slaves
, "slave server", "host" },
189 { "database", 'd', arg_string
, &database
, "database", "file" },
191 { "v4-db", '4', arg_flag
, &v4_db
, "use version 4 database" },
193 { "keytab", 'k', arg_string
, &ktname
, "keytab to use for authentication", "keytab" },
194 { "version", 0, arg_flag
, &version_flag
, NULL
, NULL
},
195 { "help", 'h', arg_flag
, &help_flag
, NULL
, NULL
}
198 static int num_args
= sizeof(args
) / sizeof(args
[0]);
202 arg_printusage (args
, num_args
, "host ...");
206 int main(int argc
, char **argv
)
210 krb5_context context
;
211 krb5_auth_context ac
;
212 krb5_principal client
;
213 krb5_principal server
;
219 krb5_get_init_creds_opt init_opts
;
220 krb5_preauthtype preauth
= KRB5_PADATA_ENC_TIMESTAMP
;
224 set_progname(argv
[0]);
226 if(getarg(args
, num_args
, argc
, argv
, &optind
))
233 fprintf(stderr
, "%s (%s)\n", __progname
, heimdal_version
);
237 ret
= krb5_init_context(&context
);
241 ret
= krb5_kt_resolve(context
, ktname
, &keytab
);
242 if(ret
) krb5_err(context
, 1, ret
, "krb5_kt_resolve");
244 ret
= krb5_make_principal(context
, &client
, NULL
, "kadmin", HPROP_NAME
, NULL
);
245 if(ret
) krb5_err(context
, 1, ret
, "krb5_make_principal");
247 krb5_get_init_creds_opt_init(&init_opts
);
248 krb5_get_init_creds_opt_set_preauth_list(&init_opts
, &preauth
, 1);
250 ret
= krb5_get_init_creds_keytab(context
, &creds
, client
, keytab
, 0, NULL
, &init_opts
);
251 if(ret
) krb5_err(context
, 1, ret
, "krb5_get_init_creds");
253 ret
= krb5_kt_close(context
, keytab
);
254 if(ret
) krb5_err(context
, 1, ret
, "krb5_kt_close");
256 ret
= krb5_cc_gen_new(context
, &mcc_ops
, &ccache
);
257 if(ret
) krb5_err(context
, 1, ret
, "krb5_cc_gen_new");
259 ret
= krb5_cc_initialize(context
, ccache
, client
);
260 if(ret
) krb5_err(context
, 1, ret
, "krb5_cc_initialize");
262 ret
= krb5_cc_store_cred(context
, ccache
, &creds
);
263 if(ret
) krb5_err(context
, 1, ret
, "krb5_cc_store_cred");
267 e
= kerb_db_set_name (database
);
268 if(e
) krb5_errx(context
, 1, "kerb_db_set_name: %s", krb_get_err_text(e
));
269 e
= kdb_get_master_key(0, &mkey
, msched
);
270 if(e
) krb5_errx(context
, 1, "kdb_get_master_key: %s", krb_get_err_text(e
));
271 e
= krb_get_lrealm(realm
, 1);
272 if(e
) krb5_errx(context
, 1, "krb_get_lrealm: %s", krb_get_err_text(e
));
276 ret
= hdb_open(context
, &db
, database
, O_RDONLY
, 0);
277 if(ret
) krb5_err(context
, 1, ret
, "hdb_open");
282 for(i
= optind
; i
< argc
; i
++){
283 fd
= open_socket(argv
[i
]);
287 ret
= krb5_sname_to_principal(context
, argv
[i
], HPROP_NAME
, KRB5_NT_SRV_HST
, &server
);
289 krb5_warn(context
, ret
, "krb5_sname_to_principal(%s)", argv
[i
]);
295 ret
= krb5_sendauth(context
,
301 AP_OPTS_MUTUAL_REQUIRED
,
310 krb5_warn(context
, ret
, "krb5_sendauth");
317 pd
.context
= context
;
318 pd
.auth_context
= ac
;
323 e
= kerb_db_iterate ((k_iter_proc_t
)conv_db
, &pd
);
326 ret
= hdb_foreach(context
, db
, func
, &pd
);
329 krb5_warn(context
, ret
, "krb5_sendauth");
334 ret
= send_priv(context
, ac
, &data
, fd
);
339 ret
= recv_priv(context
, ac
, fd
, &data
);
340 if(ret
) krb5_warn(context
, ret
, "recv_priv");
342 krb5_data_free(&data
); /* XXX */
345 if(ret
) krb5_warn(context
, ret
, "send_priv");
346 krb5_auth_con_free(context
, ac
);