xref: /freebsd/crypto/krb5/src/clients/kpasswd/kpasswd.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert 
3*7f2fe78bSCy Schubert #include "k5-platform.h"
4*7f2fe78bSCy Schubert #include <locale.h>
5*7f2fe78bSCy Schubert #include <sys/types.h>
6*7f2fe78bSCy Schubert 
7*7f2fe78bSCy Schubert #ifndef _WIN32
8*7f2fe78bSCy Schubert #include <unistd.h>
9*7f2fe78bSCy Schubert #endif
10*7f2fe78bSCy Schubert 
11*7f2fe78bSCy Schubert #include <krb5.h>
12*7f2fe78bSCy Schubert 
13*7f2fe78bSCy Schubert #define P1 _("Enter new password")
14*7f2fe78bSCy Schubert #define P2 _("Enter it again")
15*7f2fe78bSCy Schubert 
16*7f2fe78bSCy Schubert #ifdef HAVE_PWD_H
17*7f2fe78bSCy Schubert #include <pwd.h>
18*7f2fe78bSCy Schubert 
19*7f2fe78bSCy Schubert static void
get_name_from_passwd_file(char * program_name,krb5_context context,krb5_principal * me)20*7f2fe78bSCy Schubert get_name_from_passwd_file(char *program_name, krb5_context context,
21*7f2fe78bSCy Schubert                           krb5_principal *me)
22*7f2fe78bSCy Schubert {
23*7f2fe78bSCy Schubert     struct passwd *pw;
24*7f2fe78bSCy Schubert     krb5_error_code ret;
25*7f2fe78bSCy Schubert 
26*7f2fe78bSCy Schubert     pw = getpwuid(getuid());
27*7f2fe78bSCy Schubert     if (pw != NULL) {
28*7f2fe78bSCy Schubert         ret = krb5_parse_name(context, pw->pw_name, me);
29*7f2fe78bSCy Schubert         if (ret) {
30*7f2fe78bSCy Schubert             com_err(program_name, ret, _("when parsing name %s"), pw->pw_name);
31*7f2fe78bSCy Schubert             exit(1);
32*7f2fe78bSCy Schubert         }
33*7f2fe78bSCy Schubert     } else {
34*7f2fe78bSCy Schubert         fprintf(stderr, _("Unable to identify user from password file\n"));
35*7f2fe78bSCy Schubert         exit(1);
36*7f2fe78bSCy Schubert     }
37*7f2fe78bSCy Schubert }
38*7f2fe78bSCy Schubert #else /* HAVE_PWD_H */
39*7f2fe78bSCy Schubert static void
get_name_from_passwd_file(char * program_name,krb5_context context,krb5_principal * me)40*7f2fe78bSCy Schubert get_name_from_passwd_file(char *program_name, krb5_context context,
41*7f2fe78bSCy Schubert                           krb5_principal *me)
42*7f2fe78bSCy Schubert {
43*7f2fe78bSCy Schubert     fprintf(stderr, _("Unable to identify user\n"));
44*7f2fe78bSCy Schubert     exit(1);
45*7f2fe78bSCy Schubert }
46*7f2fe78bSCy Schubert #endif /* HAVE_PWD_H */
47*7f2fe78bSCy Schubert 
main(int argc,char * argv[])48*7f2fe78bSCy Schubert int main(int argc, char *argv[])
49*7f2fe78bSCy Schubert {
50*7f2fe78bSCy Schubert     krb5_error_code ret;
51*7f2fe78bSCy Schubert     krb5_context context;
52*7f2fe78bSCy Schubert     krb5_principal princ = NULL;
53*7f2fe78bSCy Schubert     char *pname, *message;
54*7f2fe78bSCy Schubert     char pw[1024];
55*7f2fe78bSCy Schubert     krb5_ccache ccache;
56*7f2fe78bSCy Schubert     krb5_get_init_creds_opt *opts = NULL;
57*7f2fe78bSCy Schubert     krb5_creds creds;
58*7f2fe78bSCy Schubert     unsigned int pwlen;
59*7f2fe78bSCy Schubert     int result_code;
60*7f2fe78bSCy Schubert     krb5_data result_code_string, result_string;
61*7f2fe78bSCy Schubert 
62*7f2fe78bSCy Schubert     setlocale(LC_ALL, "");
63*7f2fe78bSCy Schubert     if (argc > 2) {
64*7f2fe78bSCy Schubert         fprintf(stderr, _("usage: %s [principal]\n"), argv[0]);
65*7f2fe78bSCy Schubert         exit(1);
66*7f2fe78bSCy Schubert     }
67*7f2fe78bSCy Schubert 
68*7f2fe78bSCy Schubert     pname = argv[1];
69*7f2fe78bSCy Schubert 
70*7f2fe78bSCy Schubert     ret = krb5_init_context(&context);
71*7f2fe78bSCy Schubert     if (ret) {
72*7f2fe78bSCy Schubert         com_err(argv[0], ret, _("initializing kerberos library"));
73*7f2fe78bSCy Schubert         exit(1);
74*7f2fe78bSCy Schubert     }
75*7f2fe78bSCy Schubert     ret = krb5_get_init_creds_opt_alloc(context, &opts);
76*7f2fe78bSCy Schubert     if (ret) {
77*7f2fe78bSCy Schubert         com_err(argv[0], ret, _("allocating krb5_get_init_creds_opt"));
78*7f2fe78bSCy Schubert         exit(1);
79*7f2fe78bSCy Schubert     }
80*7f2fe78bSCy Schubert 
81*7f2fe78bSCy Schubert     /*
82*7f2fe78bSCy Schubert      * In order, use the first of:
83*7f2fe78bSCy Schubert      * - A name specified on the command line
84*7f2fe78bSCy Schubert      * - The principal name from an existing ccache
85*7f2fe78bSCy Schubert      * - The name corresponding to the ruid of the process
86*7f2fe78bSCy Schubert      *
87*7f2fe78bSCy Schubert      * Otherwise, it's an error.
88*7f2fe78bSCy Schubert      * We always attempt to open the default ccache in order to use FAST if
89*7f2fe78bSCy Schubert      * possible.
90*7f2fe78bSCy Schubert      */
91*7f2fe78bSCy Schubert     ret = krb5_cc_default(context, &ccache);
92*7f2fe78bSCy Schubert     if (ret) {
93*7f2fe78bSCy Schubert         com_err(argv[0], ret, _("opening default ccache"));
94*7f2fe78bSCy Schubert         exit(1);
95*7f2fe78bSCy Schubert     }
96*7f2fe78bSCy Schubert     ret = krb5_cc_get_principal(context, ccache, &princ);
97*7f2fe78bSCy Schubert     if (ret && ret != KRB5_CC_NOTFOUND && ret != KRB5_FCC_NOFILE) {
98*7f2fe78bSCy Schubert         com_err(argv[0], ret, _("getting principal from ccache"));
99*7f2fe78bSCy Schubert         exit(1);
100*7f2fe78bSCy Schubert     } else if (princ != NULL) {
101*7f2fe78bSCy Schubert         ret = krb5_get_init_creds_opt_set_fast_ccache(context, opts, ccache);
102*7f2fe78bSCy Schubert         if (ret) {
103*7f2fe78bSCy Schubert             com_err(argv[0], ret, _("while setting FAST ccache"));
104*7f2fe78bSCy Schubert             exit(1);
105*7f2fe78bSCy Schubert         }
106*7f2fe78bSCy Schubert     }
107*7f2fe78bSCy Schubert     ret = krb5_cc_close(context, ccache);
108*7f2fe78bSCy Schubert     if (ret) {
109*7f2fe78bSCy Schubert         com_err(argv[0], ret, _("closing ccache"));
110*7f2fe78bSCy Schubert         exit(1);
111*7f2fe78bSCy Schubert     }
112*7f2fe78bSCy Schubert     if (pname != NULL) {
113*7f2fe78bSCy Schubert         krb5_free_principal(context, princ);
114*7f2fe78bSCy Schubert         princ = NULL;
115*7f2fe78bSCy Schubert         ret = krb5_parse_name(context, pname, &princ);
116*7f2fe78bSCy Schubert         if (ret) {
117*7f2fe78bSCy Schubert             com_err(argv[0], ret, _("parsing client name"));
118*7f2fe78bSCy Schubert             exit(1);
119*7f2fe78bSCy Schubert         }
120*7f2fe78bSCy Schubert     }
121*7f2fe78bSCy Schubert     if (princ == NULL)
122*7f2fe78bSCy Schubert         get_name_from_passwd_file(argv[0], context, &princ);
123*7f2fe78bSCy Schubert 
124*7f2fe78bSCy Schubert     krb5_get_init_creds_opt_set_tkt_life(opts, 5 * 60);
125*7f2fe78bSCy Schubert     krb5_get_init_creds_opt_set_renew_life(opts, 0);
126*7f2fe78bSCy Schubert     krb5_get_init_creds_opt_set_forwardable(opts, 0);
127*7f2fe78bSCy Schubert     krb5_get_init_creds_opt_set_proxiable(opts, 0);
128*7f2fe78bSCy Schubert 
129*7f2fe78bSCy Schubert     ret = krb5_get_init_creds_password(context, &creds, princ, NULL,
130*7f2fe78bSCy Schubert                                        krb5_prompter_posix, NULL, 0,
131*7f2fe78bSCy Schubert                                        "kadmin/changepw", opts);
132*7f2fe78bSCy Schubert     if (ret) {
133*7f2fe78bSCy Schubert         if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
134*7f2fe78bSCy Schubert             com_err(argv[0], 0,
135*7f2fe78bSCy Schubert                     _("Password incorrect while getting initial ticket"));
136*7f2fe78bSCy Schubert         } else {
137*7f2fe78bSCy Schubert             com_err(argv[0], ret, _("getting initial ticket"));
138*7f2fe78bSCy Schubert         }
139*7f2fe78bSCy Schubert 
140*7f2fe78bSCy Schubert         krb5_get_init_creds_opt_free(context, opts);
141*7f2fe78bSCy Schubert         exit(1);
142*7f2fe78bSCy Schubert     }
143*7f2fe78bSCy Schubert 
144*7f2fe78bSCy Schubert     pwlen = sizeof(pw);
145*7f2fe78bSCy Schubert     ret = krb5_read_password(context, P1, P2, pw, &pwlen);
146*7f2fe78bSCy Schubert     if (ret) {
147*7f2fe78bSCy Schubert         com_err(argv[0], ret, _("while reading password"));
148*7f2fe78bSCy Schubert         krb5_get_init_creds_opt_free(context, opts);
149*7f2fe78bSCy Schubert         exit(1);
150*7f2fe78bSCy Schubert     }
151*7f2fe78bSCy Schubert 
152*7f2fe78bSCy Schubert     ret = krb5_change_password(context, &creds, pw, &result_code,
153*7f2fe78bSCy Schubert                                &result_code_string, &result_string);
154*7f2fe78bSCy Schubert     if (ret) {
155*7f2fe78bSCy Schubert         com_err(argv[0], ret, _("changing password"));
156*7f2fe78bSCy Schubert         krb5_get_init_creds_opt_free(context, opts);
157*7f2fe78bSCy Schubert         exit(1);
158*7f2fe78bSCy Schubert     }
159*7f2fe78bSCy Schubert 
160*7f2fe78bSCy Schubert     if (result_code) {
161*7f2fe78bSCy Schubert         if (krb5_chpw_message(context, &result_string, &message) != 0)
162*7f2fe78bSCy Schubert             message = NULL;
163*7f2fe78bSCy Schubert         printf("%.*s%s%s\n",
164*7f2fe78bSCy Schubert                (int)result_code_string.length, result_code_string.data,
165*7f2fe78bSCy Schubert                message ? ": " : "", message ? message : NULL);
166*7f2fe78bSCy Schubert         krb5_free_string(context, message);
167*7f2fe78bSCy Schubert         krb5_get_init_creds_opt_free(context, opts);
168*7f2fe78bSCy Schubert         exit(2);
169*7f2fe78bSCy Schubert     }
170*7f2fe78bSCy Schubert 
171*7f2fe78bSCy Schubert     free(result_string.data);
172*7f2fe78bSCy Schubert     free(result_code_string.data);
173*7f2fe78bSCy Schubert     krb5_get_init_creds_opt_free(context, opts);
174*7f2fe78bSCy Schubert 
175*7f2fe78bSCy Schubert     printf(_("Password changed.\n"));
176*7f2fe78bSCy Schubert     exit(0);
177*7f2fe78bSCy Schubert }
178