2 * Copyright (C) 2018 IBM Corporation
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
21 #include <talloc/talloc.h>
26 int crypt_set_password_hash(void *ctx, const char *hash)
28 struct spwd **shadow, *entry;
34 pb_log("Could not obtain access to shadow file\n");
43 /* Read all entries and modify the root entry */
45 fp = fopen("/etc/shadow", "r");
47 pb_log("Could not open shadow file, %m\n");
52 entry = fgetspent(fp);
54 shadow = talloc_realloc(ctx, shadow, struct spwd *, n + 1);
56 pb_log("Failed to allocate shadow struct\n");
61 shadow[n] = talloc_memdup(shadow, entry, sizeof(struct spwd));
63 pb_log("Could not duplicate entry for %s\n",
69 shadow[n]->sp_namp = talloc_strdup(shadow, entry->sp_namp);
70 if (strncmp(shadow[n]->sp_namp, "root", strlen("root")) == 0) {
71 shadow[n]->sp_pwdp = talloc_strdup(shadow, hash);
74 shadow[n]->sp_pwdp = talloc_strdup(shadow,
78 if (!shadow[n]->sp_namp || !shadow[n]->sp_pwdp) {
79 pb_log("Failed to allocate new fields for %s\n",
86 entry = fgetspent(fp);
90 pb_debug_fn("No entries found\n");
96 pb_debug_fn("No root user found, creating entry\n");
97 shadow = talloc_realloc(ctx, shadow, struct spwd *, n + 1);
99 pb_log("Failed to allocate shadow struct\n");
104 shadow[n] = talloc_zero(shadow, struct spwd);
105 shadow[n]->sp_namp = talloc_asprintf(shadow, "root");
106 shadow[n]->sp_pwdp = talloc_strdup(shadow, hash);
107 if (!shadow[n]->sp_namp || !shadow[n]->sp_pwdp) {
108 pb_log("Failed to allocate new fields for root entry\n");
116 fp = fopen("/etc/shadow", "w");
118 pb_log("Could not open shadow file, %m\n");
123 /* Write each entry back to keep the same format in /etc/shadow */
124 for (i = 0; i < n; i++) {
125 rc = putspent(shadow[i], fp);
127 pb_log("Failed to write back shadow entry for %s!\n",
141 static const char *crypt_hash_password(const char *password)
148 shadow = getspnam("root");
150 pb_log("Could not find root shadow\n");
154 if (shadow->sp_pwdp && strlen(shadow->sp_pwdp)) {
155 salt = shadow->sp_pwdp;
157 for (i = 0; i < 16; i++)
158 new_salt[i] = random() % 94 + 32;
160 salt = talloc_asprintf(password, "$6$%s", new_salt);
163 hash = crypt(password ?: "", salt);
165 pb_log("Could not create hash, %m\n");
172 int crypt_set_password(void *ctx, const char *password)
176 if (!password || !strlen(password))
177 return crypt_set_password_hash(ctx, "");
179 hash = crypt_hash_password(password);
183 return crypt_set_password_hash(ctx, hash);
186 char *crypt_get_hash(void *ctx)
190 shadow = getspnam("root");
192 pb_log("Could not find root shadow\n");
196 return talloc_strdup(ctx, shadow->sp_pwdp);
199 bool crypt_check_password(const char *password)
204 shadow = getspnam("root");
206 pb_log("Could not find root shadow\n");
210 hash = crypt(password ? : "", shadow->sp_pwdp);
212 pb_log("Could not create hash, %m\n");
216 return strncmp(shadow->sp_pwdp, hash, strlen(shadow->sp_pwdp)) == 0;