chpass_s.c revision 178825
155682Smarkm/*
2178825Sdfr * Copyright (c) 1997-2006 Kungliga Tekniska H�gskolan
355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden).
455682Smarkm * All rights reserved.
555682Smarkm *
655682Smarkm * Redistribution and use in source and binary forms, with or without
755682Smarkm * modification, are permitted provided that the following conditions
855682Smarkm * are met:
955682Smarkm *
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1455682Smarkm *    notice, this list of conditions and the following disclaimer in the
1555682Smarkm *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors
1855682Smarkm *    may be used to endorse or promote products derived from this software
1955682Smarkm *    without specific prior written permission.
2055682Smarkm *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3155682Smarkm * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "kadm5_locl.h"
3555682Smarkm
36178825SdfrRCSID("$Id: chpass_s.c 20608 2007-05-08 07:11:48Z lha $");
3755682Smarkm
3872445Sassarstatic kadm5_ret_t
3972445Sassarchange(void *server_handle,
4072445Sassar       krb5_principal princ,
41178825Sdfr       const char *password,
4272445Sassar       int cond)
4355682Smarkm{
4455682Smarkm    kadm5_server_context *context = server_handle;
45178825Sdfr    hdb_entry_ex ent;
4655682Smarkm    kadm5_ret_t ret;
4772445Sassar    Key *keys;
4872445Sassar    size_t num_keys;
4972445Sassar    int cmp = 1;
5072445Sassar
51178825Sdfr    memset(&ent, 0, sizeof(ent));
52178825Sdfr    ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
5355682Smarkm    if(ret)
5455682Smarkm	return ret;
55178825Sdfr    ret = context->db->hdb_fetch(context->context, context->db, princ,
56178825Sdfr				 HDB_F_DECRYPT|HDB_F_GET_ANY, &ent);
5755682Smarkm    if(ret == HDB_ERR_NOENTRY)
5855682Smarkm	goto out;
5972445Sassar
60178825Sdfr    num_keys = ent.entry.keys.len;
61178825Sdfr    keys     = ent.entry.keys.val;
6272445Sassar
63178825Sdfr    ent.entry.keys.len = 0;
64178825Sdfr    ent.entry.keys.val = NULL;
6572445Sassar
66178825Sdfr    ret = _kadm5_set_keys(context, &ent.entry, password);
6772445Sassar    if(ret) {
68178825Sdfr	_kadm5_free_keys (context->context, num_keys, keys);
6955682Smarkm	goto out2;
7072445Sassar    }
71178825Sdfr    ent.entry.kvno++;
7272445Sassar    if (cond)
73178825Sdfr	cmp = _kadm5_cmp_keys (ent.entry.keys.val, ent.entry.keys.len,
7472445Sassar			       keys, num_keys);
75178825Sdfr    _kadm5_free_keys (context->context, num_keys, keys);
7672445Sassar
77127808Snectar    if (cmp == 0) {
78127808Snectar	krb5_set_error_string(context->context, "Password reuse forbidden");
79127808Snectar	ret = KADM5_PASS_REUSE;
80178825Sdfr	goto out2;
81127808Snectar    }
82178825Sdfr
83178825Sdfr    ret = _kadm5_set_modifier(context, &ent.entry);
8455682Smarkm    if(ret)
8555682Smarkm	goto out2;
8655682Smarkm
87178825Sdfr    ret = _kadm5_bump_pw_expire(context, &ent.entry);
8872445Sassar    if (ret)
8972445Sassar	goto out2;
9055682Smarkm
91178825Sdfr    ret = hdb_seal_keys(context->context, context->db, &ent.entry);
9272445Sassar    if (ret)
9372445Sassar	goto out2;
9472445Sassar
95178825Sdfr    ret = context->db->hdb_store(context->context, context->db,
96178825Sdfr				 HDB_F_REPLACE, &ent);
97178825Sdfr    if (ret)
98178825Sdfr	goto out2;
99178825Sdfr
10055682Smarkm    kadm5_log_modify (context,
101178825Sdfr		      &ent.entry,
10255682Smarkm		      KADM5_PRINCIPAL | KADM5_MOD_NAME | KADM5_MOD_TIME |
103178825Sdfr		      KADM5_KEY_DATA | KADM5_KVNO | KADM5_PW_EXPIRATION |
104178825Sdfr		      KADM5_TL_DATA);
105178825Sdfr
10655682Smarkmout2:
10755682Smarkm    hdb_free_entry(context->context, &ent);
10855682Smarkmout:
109178825Sdfr    context->db->hdb_close(context->context, context->db);
11055682Smarkm    return _kadm5_error_code(ret);
11155682Smarkm}
11255682Smarkm
11372445Sassar
11472445Sassar
11572445Sassar/*
11672445Sassar * change the password of `princ' to `password' if it's not already that.
11772445Sassar */
11872445Sassar
11955682Smarkmkadm5_ret_t
12072445Sassarkadm5_s_chpass_principal_cond(void *server_handle,
12172445Sassar			      krb5_principal princ,
122178825Sdfr			      const char *password)
12372445Sassar{
12472445Sassar    return change (server_handle, princ, password, 1);
12572445Sassar}
12672445Sassar
12772445Sassar/*
12872445Sassar * change the password of `princ' to `password'
12972445Sassar */
13072445Sassar
13172445Sassarkadm5_ret_t
13272445Sassarkadm5_s_chpass_principal(void *server_handle,
13372445Sassar			 krb5_principal princ,
134178825Sdfr			 const char *password)
13572445Sassar{
13672445Sassar    return change (server_handle, princ, password, 0);
13772445Sassar}
13872445Sassar
13972445Sassar/*
14072445Sassar * change keys for `princ' to `keys'
14172445Sassar */
14272445Sassar
14372445Sassarkadm5_ret_t
14455682Smarkmkadm5_s_chpass_principal_with_key(void *server_handle,
14555682Smarkm				  krb5_principal princ,
14655682Smarkm				  int n_key_data,
14755682Smarkm				  krb5_key_data *key_data)
14855682Smarkm{
14955682Smarkm    kadm5_server_context *context = server_handle;
150178825Sdfr    hdb_entry_ex ent;
15155682Smarkm    kadm5_ret_t ret;
152178825Sdfr
153178825Sdfr    memset(&ent, 0, sizeof(ent));
154178825Sdfr    ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
15555682Smarkm    if(ret)
15655682Smarkm	return ret;
157178825Sdfr    ret = context->db->hdb_fetch(context->context, context->db, princ,
158178825Sdfr				 HDB_F_GET_ANY, &ent);
15955682Smarkm    if(ret == HDB_ERR_NOENTRY)
16055682Smarkm	goto out;
161178825Sdfr    ret = _kadm5_set_keys2(context, &ent.entry, n_key_data, key_data);
16255682Smarkm    if(ret)
16355682Smarkm	goto out2;
164178825Sdfr    ent.entry.kvno++;
165178825Sdfr    ret = _kadm5_set_modifier(context, &ent.entry);
16655682Smarkm    if(ret)
16755682Smarkm	goto out2;
168178825Sdfr    ret = _kadm5_bump_pw_expire(context, &ent.entry);
16972445Sassar    if (ret)
17072445Sassar	goto out2;
17155682Smarkm
172178825Sdfr    ret = hdb_seal_keys(context->context, context->db, &ent.entry);
17372445Sassar    if (ret)
17472445Sassar	goto out2;
17555682Smarkm
176178825Sdfr    ret = context->db->hdb_store(context->context, context->db,
177178825Sdfr				 HDB_F_REPLACE, &ent);
178178825Sdfr    if (ret)
179178825Sdfr	goto out2;
180178825Sdfr
18155682Smarkm    kadm5_log_modify (context,
182178825Sdfr		      &ent.entry,
18355682Smarkm		      KADM5_PRINCIPAL | KADM5_MOD_NAME | KADM5_MOD_TIME |
184178825Sdfr		      KADM5_KEY_DATA | KADM5_KVNO | KADM5_PW_EXPIRATION |
185178825Sdfr		      KADM5_TL_DATA);
186178825Sdfr
18755682Smarkmout2:
18855682Smarkm    hdb_free_entry(context->context, &ent);
18955682Smarkmout:
190178825Sdfr    context->db->hdb_close(context->context, context->db);
19155682Smarkm    return _kadm5_error_code(ret);
19255682Smarkm}
193