aboutsummaryrefslogtreecommitdiff
path: root/src/mac/kpasswd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mac/kpasswd.c')
-rw-r--r--src/mac/kpasswd.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/mac/kpasswd.c b/src/mac/kpasswd.c
new file mode 100644
index 0000000..03db03f
--- /dev/null
+++ b/src/mac/kpasswd.c
@@ -0,0 +1,151 @@
+#include <stdio.h>
+#include <sys/types.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#if TARGET_HEADER_FRAMEWORK
+ #include <Kerberos/Kerberos.h>
+#else
+ #include <krb5.h>
+#endif
+
+#define P1 "Enter new password: "
+#define P2 "Enter it again: "
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+
+static
+void get_name_from_passwd_file(program_name, kcontext, me)
+ char * program_name;
+ krb5_context kcontext;
+ krb5_principal * me;
+{
+ struct passwd *pw;
+ krb5_error_code code;
+ if ((pw = getpwuid((int) getuid()))) {
+ if ((code = krb5_parse_name(kcontext, pw->pw_name, me))) {
+ com_err (program_name, code, "when parsing name %s", pw->pw_name);
+ exit(1);
+ }
+ } else {
+ fprintf(stderr, "Unable to identify user from password file\n");
+ exit(1);
+ }
+}
+#else /* HAVE_PWD_H */
+void get_name_from_passwd_file(kcontext, me)
+ krb5_context kcontext;
+ krb5_principal * me;
+{
+ fprintf(stderr, "Unable to identify user\n");
+ exit(1);
+}
+#endif /* HAVE_PWD_H */
+
+int main(int argc, char *argv[])
+{
+ krb5_error_code ret;
+ krb5_context context;
+ krb5_principal princ;
+ char *pname;
+ krb5_ccache ccache;
+ krb5_get_init_creds_opt opts;
+ krb5_creds creds;
+
+ char pw[1024];
+ unsigned int pwlen;
+ int result_code;
+ krb5_data result_code_string, result_string;
+
+ if (argc > 2) {
+ fprintf(stderr, "usage: %s [principal]\n", argv[0]);
+ exit(1);
+ }
+
+ pname = argv[1];
+
+ ret = krb5_init_context(&context);
+ if (ret) {
+ com_err(argv[0], ret, "initializing kerberos library");
+ exit(1);
+ }
+
+ /* in order, use the first of:
+ - a name specified on the command line
+ - the principal name from an existing ccache
+ - the name corresponding to the ruid of the process
+
+ otherwise, it's an error.
+ */
+
+ if (pname) {
+ if ((ret = krb5_parse_name(context, pname, &princ))) {
+ com_err(argv[0], ret, "parsing client name");
+ exit(1);
+ }
+ } else if ((ret = krb5_cc_default(context, &ccache)) != KRB5_CC_NOTFOUND) {
+ if (ret) {
+ com_err(argv[0], ret, "opening default ccache");
+ exit(1);
+ }
+
+ if ((ret = krb5_cc_get_principal(context, ccache, &princ))) {
+ com_err(argv[0], ret, "getting principal from ccache");
+ exit(1);
+ }
+
+ if ((ret = krb5_cc_close(context, ccache))) {
+ com_err(argv[0], ret, "closing ccache");
+ exit(1);
+ }
+ } else {
+ get_name_from_passwd_file(argv[0], context, &princ);
+ }
+
+ krb5_get_init_creds_opt_init(&opts);
+ krb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
+ krb5_get_init_creds_opt_set_renew_life(&opts, 0);
+ krb5_get_init_creds_opt_set_forwardable(&opts, 0);
+ krb5_get_init_creds_opt_set_proxiable(&opts, 0);
+
+ if ((ret = krb5_get_init_creds_password(context, &creds, princ, NULL,
+ krb5_prompter_posix, NULL,
+ 0, "kadmin/changepw", &opts))) {
+ if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY)
+ com_err(argv[0], 0,
+ "Password incorrect while getting initial ticket");
+ else
+ com_err(argv[0], ret, "getting initial ticket");
+ exit(1);
+ }
+
+ pwlen = sizeof(pw);
+ if ((ret = krb5_read_password(context, P1, P2, pw, &pwlen))) {
+ com_err(argv[0], ret, "while reading password");
+ exit(1);
+ }
+
+ if ((ret = krb5_change_password(context, &creds, pw,
+ &result_code, &result_code_string,
+ &result_string))) {
+ com_err(argv[0], ret, "changing password");
+ exit(1);
+ }
+
+ if (result_code) {
+ printf("%.*s%s%.*s\n",
+ (int) result_code_string.length, result_code_string.data,
+ result_string.length?": ":"",
+ (int) result_string.length, result_string.data);
+ exit(2);
+ }
+
+ free(result_string.data);
+ free(result_code_string.data);
+
+ printf("Password changed.\n");
+ exit(0);
+}