4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright (c) 2016 by Delphix. All rights reserved.
37 #include <nss_dbdefs.h>
44 #include "passwdutil.h"
48 #define MAX_INT_LEN 11 /* 10+1 %d buflen for words/ints [not longs] */
50 #define STRDUP_OR_RET(to, from) \
51 if ((to = strdup(from)) == NULL) \
54 #define STRDUP_OR_ERR(to, from, err) \
55 if (((to) = strdup(from)) == NULL) \
58 #define NUM_TO_STR(to, from) \
60 char nb[MAX_INT_LEN]; \
61 if (snprintf(nb, MAX_INT_LEN, "%d", (from)) >= MAX_INT_LEN) \
63 STRDUP_OR_RET(to, nb); \
66 #define NEW_ATTR(p, i, attr, val) \
68 p[i] = new_attr(attr, (val)); \
74 int ldap_getattr(char *name
, attrlist
*item
, pwu_repository_t
*rep
);
75 int ldap_getpwnam(char *name
, attrlist
*items
, pwu_repository_t
*rep
,
77 int ldap_update(attrlist
*items
, pwu_repository_t
*rep
, void *buf
);
78 int ldap_putpwnam(char *name
, char *oldpw
, pwu_repository_t
*rep
, void *buf
);
79 int ldap_user_to_authenticate(char *name
, pwu_repository_t
*rep
,
80 char **auth_user
, int *privileged
);
83 * ldap function pointer table, used by passwdutil_init to initialize
84 * the global Repository-OPerations table "rops"
86 struct repops ldap_repops
= {
87 NULL
, /* checkhistory */
92 ldap_user_to_authenticate
,
98 * structure used to keep state between get/update/put calls
101 char *passwd
; /* encrypted password */
103 ns_ldap_attr_t
**pattrs
; /* passwd attrs */
104 int npattrs
; /* max attrs */
106 ns_ldap_attr_t
**sattrs
; /* passwd attrs */
107 int nsattrs
; /* max attrs */
108 boolean_t shadow_update_enabled
; /* shadow update configured */
112 * The following define's are taken from
113 * usr/src/lib/nsswitch/ldap/common/getpwnam.c
116 /* passwd attributes filters */
118 #define _PWD_UID "uid"
119 #define _PWD_USERPASSWORD "userpassword"
120 #define _PWD_UIDNUMBER "uidnumber"
121 #define _PWD_GIDNUMBER "gidnumber"
122 #define _PWD_GECOS "gecos"
123 #define _PWD_DESCRIPTION "description"
124 #define _PWD_HOMEDIRECTORY "homedirectory"
125 #define _PWD_LOGINSHELL "loginshell"
127 #define _PWD_MAX_ATTR 10 /* 9+NULL */
129 /* shadow attributes filters */
130 #define _S_LASTCHANGE "shadowlastchange"
131 #define _S_MIN "shadowmin"
132 #define _S_MAX "shadowmax"
133 #define _S_WARNING "shadowwarning"
134 #define _S_INACTIVE "shadowinactive"
135 #define _S_EXPIRE "shadowexpire"
136 #define _S_FLAG "shadowflag"
138 #define _S_MAX_ATTR 8 /* 7+NULL */
141 * Frees up an ldapbuf_t
145 free_ldapbuf(ldapbuf_t
*p
)
152 (void) memset(p
->passwd
, 0, strlen(p
->passwd
));
160 for (i
= 0; i
< p
->npattrs
; i
++) {
161 if (p
->pattrs
[i
] != NULL
) {
162 free(p
->pattrs
[i
]->attrvalue
[0]);
169 for (i
= 0; i
< p
->nsattrs
; i
++) {
170 if (p
->sattrs
[i
] != NULL
) {
171 free(p
->sattrs
[i
]->attrvalue
[0]);
180 * int ldap_user_to_authenticate(user, rep, auth_user, privileged)
182 * If the Shadow Update functionality is enabled, then we check to
183 * see if the caller has 0 as the euid or has all zone privs. If so,
184 * the caller would be able to modify shadow(4) data stored on the
185 * LDAP server. Otherwise, when LDAP Shadow Update is not enabled,
186 * we can't determine whether the user is "privileged" in the LDAP
187 * sense. The operation should be attempted and will succeed if the
188 * user had privileges. For our purposes, we say that the user is
189 * privileged if they are attempting to change another user's
190 * password attributes.
193 ldap_user_to_authenticate(char *user
, pwu_repository_t
*rep
,
194 char **auth_user
, int *privileged
)
198 uid_t priviledged_uid
;
199 int res
= PWU_SUCCESS
;
201 if (strcmp(user
, "root") == 0)
202 return (PWU_NOT_FOUND
);
204 if ((pw
= getpwnam_from(user
, rep
, REP_LDAP
)) == NULL
)
205 return (PWU_NOT_FOUND
);
210 * need equivalent of write access to /etc/shadow
211 * the privilege escalation model is euid == 0 || all zone privs
213 if (__ns_ldap_is_shadow_update_enabled()) {
216 priv
= (geteuid() == 0);
218 priv_set_t
*ps
= priv_allocset(); /* caller */
219 priv_set_t
*zs
; /* zone */
221 (void) getppriv(PRIV_EFFECTIVE
, ps
);
222 zs
= priv_str_to_set("zone", ",", NULL
);
223 priv
= priv_isequalset(ps
, zs
);
228 * priv can change anyone's password,
229 * only root isn't prompted.
231 *privileged
= 0; /* for proper prompting */
237 } else if (uid
== pw
->pw_uid
) {
238 STRDUP_OR_ERR(*auth_user
, user
, res
);
246 if (uid
== pw
->pw_uid
) {
247 /* changing our own, not privileged */
249 STRDUP_OR_RET(*auth_user
, user
);
257 * specific case for root
258 * we want 'user' to be authenticated.
261 priviledged_uid
= pw
->pw_uid
;
263 priviledged_uid
= uid
;
265 getpwuid_r(priviledged_uid
, &pwr
, pwd_buf
,
266 sizeof (pwd_buf
), &pwdp
);
268 STRDUP_OR_ERR(*auth_user
, pwr
.pw_name
, res
);
270 /* hmm. can't find name of current user...??? */
272 if ((*auth_user
= malloc(MAX_INT_LEN
)) == NULL
) {
275 (void) snprintf(*auth_user
, MAX_INT_LEN
, "%d",
285 * int ldap_getattr(name, item, rep)
287 * retrieve attributes specified in "item" for user "name".
291 ldap_getattr(char *name
, attrlist
*items
, pwu_repository_t
*rep
)
296 struct passwd
*pw
= NULL
;
297 struct spwd
*spw
= NULL
;
299 res
= ldap_getpwnam(name
, items
, rep
, (void **)&ldapbuf
);
300 if (res
!= PWU_SUCCESS
)
306 for (w
= items
; res
== PWU_SUCCESS
&& w
!= NULL
; w
= w
->next
) {
309 STRDUP_OR_ERR(w
->data
.val_s
, pw
->pw_name
, res
);
312 STRDUP_OR_ERR(w
->data
.val_s
, pw
->pw_comment
, res
);
315 STRDUP_OR_ERR(w
->data
.val_s
, pw
->pw_gecos
, res
);
318 STRDUP_OR_ERR(w
->data
.val_s
, pw
->pw_dir
, res
);
321 STRDUP_OR_ERR(w
->data
.val_s
, pw
->pw_shell
, res
);
324 case ATTR_PASSWD_SERVER_POLICY
:
325 STRDUP_OR_ERR(w
->data
.val_s
, spw
->sp_pwdp
, res
);
328 STRDUP_OR_ERR(w
->data
.val_s
, pw
->pw_age
, res
);
331 STRDUP_OR_ERR(w
->data
.val_s
, "ldap", res
);
336 w
->data
.val_i
= pw
->pw_uid
;
339 w
->data
.val_i
= pw
->pw_gid
;
342 if (ldapbuf
->shadow_update_enabled
)
343 w
->data
.val_i
= spw
->sp_lstchg
;
348 if (ldapbuf
->shadow_update_enabled
)
349 w
->data
.val_i
= spw
->sp_min
;
354 if (ldapbuf
->shadow_update_enabled
)
355 w
->data
.val_i
= spw
->sp_max
;
360 if (ldapbuf
->shadow_update_enabled
)
361 w
->data
.val_i
= spw
->sp_warn
;
366 if (ldapbuf
->shadow_update_enabled
)
367 w
->data
.val_i
= spw
->sp_inact
;
372 if (ldapbuf
->shadow_update_enabled
)
373 w
->data
.val_i
= spw
->sp_expire
;
378 if (ldapbuf
->shadow_update_enabled
)
379 w
->data
.val_i
= spw
->sp_flag
;
381 case ATTR_FAILED_LOGINS
:
382 w
->data
.val_i
= spw
->sp_flag
& FAILCOUNT_MASK
;
390 free_ldapbuf(ldapbuf
);
396 * int ldap_getpwnam(name, items, rep, buf)
398 * There is no need to get the old values from the ldap
399 * server, as the update will update each item individually.
400 * Therefore, we only allocate a buffer that will be used by
401 * _update and _putpwnam to hold the attributes to update.
403 * Only when we're about to update a password, we need to retrieve
404 * the old password since it contains salt-information.
408 ldap_getpwnam(char *name
, attrlist
*items
, pwu_repository_t
*rep
,
415 * [sp]attrs is treated as NULL terminated
418 ldapbuf
= calloc(1, sizeof (ldapbuf_t
));
422 ldapbuf
->pattrs
= calloc(_PWD_MAX_ATTR
, sizeof (ns_ldap_attr_t
*));
423 if (ldapbuf
->pattrs
== NULL
)
425 ldapbuf
->npattrs
= _PWD_MAX_ATTR
;
427 ldapbuf
->sattrs
= calloc(_S_MAX_ATTR
, sizeof (ns_ldap_attr_t
*));
428 if (ldapbuf
->sattrs
== NULL
)
430 ldapbuf
->nsattrs
= _S_MAX_ATTR
;
432 res
= dup_pw(&ldapbuf
->pwd
, getpwnam_from(name
, rep
, REP_LDAP
));
433 if (res
!= PWU_SUCCESS
)
436 res
= dup_spw(&ldapbuf
->spwd
, getspnam_from(name
, rep
, REP_LDAP
));
437 if (res
!= PWU_SUCCESS
)
440 char *spw
= ldapbuf
->spwd
->sp_pwdp
;
441 if (spw
!= NULL
&& *spw
!= '\0') {
442 ldapbuf
->passwd
= strdup(spw
);
443 if (ldapbuf
->passwd
== NULL
)
446 ldapbuf
->passwd
= NULL
;
449 /* remember if shadow update is enabled */
450 ldapbuf
->shadow_update_enabled
= __ns_ldap_is_shadow_update_enabled();
452 *buf
= (void *)ldapbuf
;
453 return (PWU_SUCCESS
);
456 free_ldapbuf(ldapbuf
);
462 * new_attr(name, value)
464 * create a new LDAP attribute to be sent to the server
467 new_attr(char *name
, char *value
)
471 tmp
= malloc(sizeof (*tmp
));
473 tmp
->attrname
= name
;
474 tmp
->attrvalue
= (char **)calloc(2, sizeof (char *));
475 if (tmp
->attrvalue
== NULL
) {
479 tmp
->attrvalue
[0] = value
;
480 tmp
->value_count
= 1;
489 * returns '1' if a ATTR_MAX with value != -1 is present. (in other words:
490 * if password aging is to be turned on).
493 max_present(attrlist
*list
)
496 if (list
->type
== ATTR_MAX
&& list
->data
.val_i
!= -1)
504 * attr_addmod(attrs, idx, item, val)
506 * Adds or updates attribute 'item' in ldap_attrs list to value
507 * update idx if item is added
508 * return: -1 - PWU_NOMEM/error, 0 - success
511 attr_addmod(ns_ldap_attr_t
**attrs
, int *idx
, char *item
, int value
)
513 char numbuf
[MAX_INT_LEN
], *strp
;
516 /* stringize the value or abort */
517 if (snprintf(numbuf
, MAX_INT_LEN
, "%d", value
) >= MAX_INT_LEN
)
520 /* check for existence and modify existing */
521 for (i
= 0; i
< *idx
; i
++) {
522 if (attrs
[i
] != NULL
&&
523 strcmp(item
, attrs
[i
]->attrname
) == 0) {
524 strp
= strdup(numbuf
);
527 free(attrs
[i
]->attrvalue
[0]);
528 attrs
[i
]->attrvalue
[0] = strp
;
533 strp
= strdup(numbuf
);
536 attrs
[*idx
] = new_attr(item
, strp
);
537 if (attrs
[*idx
] == NULL
)
544 * ldap_update(items, rep, buf)
546 * create LDAP attributes in 'buf' for each attribute in 'items'.
550 ldap_update(attrlist
*items
, pwu_repository_t
*rep
, void *buf
)
553 ldapbuf_t
*ldapbuf
= (ldapbuf_t
*)buf
;
555 ns_ldap_attr_t
**pattrs
= ldapbuf
->pattrs
;
557 ns_ldap_attr_t
**sattrs
= ldapbuf
->sattrs
;
564 int rc
= PWU_SUCCESS
;
565 int aging_needed
= 0;
572 * if sp_max==0 and shadow update is enabled:
573 * disable passwd aging after updating the password
575 disable_aging
= (spw
!= NULL
&& spw
->sp_max
== 0 &&
576 ldapbuf
->shadow_update_enabled
);
578 for (p
= items
; p
!= NULL
; p
= p
->next
) {
582 * There is a special case for ldap: if the
583 * password is to be deleted (-d to passwd),
584 * p->data.val_s will be NULL.
586 if (p
->data
.val_s
== NULL
) {
587 if (!ldapbuf
->shadow_update_enabled
)
588 return (PWU_CHANGE_NOT_ALLOWED
);
590 sizeof ("{crypt}" NS_LDAP_NO_UNIX_PASSWORD
);
591 val
= malloc(cryptlen
);
594 (void) snprintf(val
, cryptlen
,
595 "{crypt}" NS_LDAP_NO_UNIX_PASSWORD
);
596 } else { /* not deleting password */
597 salt
= crypt_gensalt(ldapbuf
->passwd
,
604 /* algorithm problem? */
605 syslog(LOG_AUTH
| LOG_ALERT
,
606 "passwdutil: crypt_gensalt "
608 return (PWU_UPDATE_FAILED
);
611 pwd
= crypt(p
->data
.val_s
, salt
);
613 cryptlen
= strlen(pwd
) + sizeof ("{crypt}");
614 val
= malloc(cryptlen
);
617 (void) snprintf(val
, cryptlen
,
622 * If not managing passwordAccount,
623 * insert the new password in the
624 * passwd attr array and break.
626 if (!ldapbuf
->shadow_update_enabled
) {
627 NEW_ATTR(pattrs
, pidx
,
628 _PWD_USERPASSWORD
, val
);
633 * Managing passwordAccount, insert the
634 * new password, along with lastChange and
635 * shadowFlag, in the shadow attr array.
637 NEW_ATTR(sattrs
, sidx
, _PWD_USERPASSWORD
, val
);
639 if (attr_addmod(sattrs
, &sidx
, _S_LASTCHANGE
,
642 spw
->sp_lstchg
= DAY_NOW_32
;
644 if (attr_addmod(sattrs
, &sidx
, _S_FLAG
,
645 spw
->sp_flag
& ~FAILCOUNT_MASK
) < 0)
647 spw
->sp_flag
&= ~FAILCOUNT_MASK
; /* reset count */
650 case ATTR_PASSWD_SERVER_POLICY
:
652 * For server policy, don't crypt the password,
653 * send the password as is to the server and
654 * let the LDAP server do its own password
657 STRDUP_OR_RET(val
, p
->data
.val_s
);
659 NEW_ATTR(pattrs
, pidx
, _PWD_USERPASSWORD
, val
);
663 NEW_ATTR(pattrs
, pidx
, _PWD_DESCRIPTION
, p
->data
.val_s
);
666 if (!ldapbuf
->shadow_update_enabled
) {
667 NEW_ATTR(pattrs
, pidx
, _PWD_GECOS
,
670 NEW_ATTR(sattrs
, sidx
, _PWD_GECOS
,
675 if (!ldapbuf
->shadow_update_enabled
) {
676 NEW_ATTR(pattrs
, pidx
, _PWD_HOMEDIRECTORY
,
679 NEW_ATTR(sattrs
, sidx
, _PWD_HOMEDIRECTORY
,
684 if (!ldapbuf
->shadow_update_enabled
) {
685 NEW_ATTR(pattrs
, pidx
, _PWD_LOGINSHELL
,
688 NEW_ATTR(sattrs
, sidx
, _PWD_LOGINSHELL
,
692 /* We don't update NAME, UID, GID */
696 /* Unsupported item */
699 case ATTR_LOCK_ACCOUNT
:
700 if (!ldapbuf
->shadow_update_enabled
)
701 break; /* not managing passwordAccount */
702 if (spw
->sp_pwdp
== NULL
) {
703 spw
->sp_pwdp
= LOCKSTRING
;
704 } else if ((strncmp(spw
->sp_pwdp
, LOCKSTRING
,
705 sizeof (LOCKSTRING
)-1) != 0) &&
706 (strcmp(spw
->sp_pwdp
, NOLOGINSTRING
) != 0)) {
707 len
= sizeof (LOCKSTRING
)-1 +
708 strlen(spw
->sp_pwdp
) + 1 +
714 (void) strlcpy(pwd
, "{crypt}", len
);
715 (void) strlcat(pwd
, LOCKSTRING
, len
);
716 (void) strlcat(pwd
, spw
->sp_pwdp
, len
);
719 NEW_ATTR(sattrs
, sidx
, _PWD_USERPASSWORD
,
722 if (attr_addmod(sattrs
, &sidx
, _S_LASTCHANGE
,
725 spw
->sp_lstchg
= DAY_NOW_32
;
728 case ATTR_UNLOCK_ACCOUNT
:
729 if (!ldapbuf
->shadow_update_enabled
)
730 break; /* not managing passwordAccount */
732 strncmp(spw
->sp_pwdp
, LOCKSTRING
,
733 sizeof (LOCKSTRING
)-1) == 0) {
734 len
= (sizeof ("{crypt}") -
735 sizeof (LOCKSTRING
)) +
736 strlen(spw
->sp_pwdp
) + 1;
741 (void) strlcpy(pwd
, "{crypt}", len
);
742 (void) strlcat(pwd
, spw
->sp_pwdp
+
743 sizeof (LOCKSTRING
)-1, len
);
747 NEW_ATTR(sattrs
, sidx
, _PWD_USERPASSWORD
,
749 if (attr_addmod(sattrs
, &sidx
, _S_LASTCHANGE
,
752 spw
->sp_lstchg
= DAY_NOW_32
;
756 case ATTR_NOLOGIN_ACCOUNT
:
757 if (!ldapbuf
->shadow_update_enabled
)
758 break; /* not managing passwordAccount */
760 STRDUP_OR_RET(spw
->sp_pwdp
, "{crypt}" NOLOGINSTRING
);
761 NEW_ATTR(sattrs
, sidx
, _PWD_USERPASSWORD
, spw
->sp_pwdp
);
762 if (attr_addmod(sattrs
, &sidx
, _S_LASTCHANGE
,
765 spw
->sp_lstchg
= DAY_NOW_32
;
768 case ATTR_EXPIRE_PASSWORD
:
769 if (!ldapbuf
->shadow_update_enabled
)
770 break; /* not managing passwordAccount */
772 NEW_ATTR(sattrs
, sidx
, _S_LASTCHANGE
, val
);
776 if (!ldapbuf
->shadow_update_enabled
)
777 break; /* not managing passwordAccount */
778 NUM_TO_STR(val
, p
->data
.val_i
);
779 NEW_ATTR(sattrs
, sidx
, _S_LASTCHANGE
, val
);
783 if (!ldapbuf
->shadow_update_enabled
)
784 break; /* not managing passwordAccount */
785 if (spw
->sp_max
== -1 && p
->data
.val_i
!= -1 &&
786 max_present(p
->next
) == 0)
787 return (PWU_AGING_DISABLED
);
788 NUM_TO_STR(val
, p
->data
.val_i
);
789 NEW_ATTR(sattrs
, sidx
, _S_MIN
, val
);
794 if (!ldapbuf
->shadow_update_enabled
)
795 break; /* not managing passwordAccount */
796 if (p
->data
.val_i
== -1) {
797 /* Turn off aging. Reset min and warn too */
798 spw
->sp_max
= spw
->sp_min
= spw
->sp_warn
= -1;
800 NEW_ATTR(sattrs
, sidx
, _S_MIN
, val
);
802 NEW_ATTR(sattrs
, sidx
, _S_WARNING
, val
);
804 /* Turn account aging on */
805 if (spw
->sp_min
== -1) {
807 * minage was not set with command-
808 * line option: set to zero
812 NEW_ATTR(sattrs
, sidx
, _S_MIN
,
816 * If aging was turned off, we update lstchg.
817 * We take care not to update lstchg if the
818 * user has no password, otherwise the user
819 * might not be required to provide a password
820 * the next time they log in.
822 * Also, if lstchg != -1 (i.e., not set)
823 * we keep the old value.
825 if (spw
->sp_max
== -1 &&
826 spw
->sp_pwdp
!= NULL
&& *spw
->sp_pwdp
&&
827 spw
->sp_lstchg
== -1) {
828 if (attr_addmod(sattrs
, &sidx
,
832 spw
->sp_lstchg
= DAY_NOW_32
;
835 NUM_TO_STR(val
, p
->data
.val_i
);
836 NEW_ATTR(sattrs
, sidx
, _S_MAX
, val
);
841 if (!ldapbuf
->shadow_update_enabled
)
842 break; /* not managing passwordAccount */
843 if (spw
->sp_max
== -1 &&
844 p
->data
.val_i
!= -1 && max_present(p
->next
) == 0)
845 return (PWU_AGING_DISABLED
);
846 NUM_TO_STR(val
, p
->data
.val_i
);
847 NEW_ATTR(sattrs
, sidx
, _S_WARNING
, val
);
851 if (!ldapbuf
->shadow_update_enabled
)
852 break; /* not managing passwordAccount */
853 NUM_TO_STR(val
, p
->data
.val_i
);
854 NEW_ATTR(sattrs
, sidx
, _S_INACTIVE
, val
);
858 if (!ldapbuf
->shadow_update_enabled
)
859 break; /* not managing passwordAccount */
860 NUM_TO_STR(val
, p
->data
.val_i
);
861 NEW_ATTR(sattrs
, sidx
, _S_EXPIRE
, val
);
865 if (!ldapbuf
->shadow_update_enabled
)
866 break; /* not managing passwordAccount */
867 NUM_TO_STR(val
, p
->data
.val_i
);
868 NEW_ATTR(sattrs
, sidx
, _S_FLAG
, val
);
870 case ATTR_INCR_FAILED_LOGINS
:
871 if (!ldapbuf
->shadow_update_enabled
) {
872 rc
= PWU_CHANGE_NOT_ALLOWED
;
873 break; /* not managing passwordAccount */
875 count
= (spw
->sp_flag
& FAILCOUNT_MASK
) + 1;
876 spw
->sp_flag
&= ~FAILCOUNT_MASK
;
877 spw
->sp_flag
|= min(FAILCOUNT_MASK
, count
);
878 p
->data
.val_i
= count
;
879 NUM_TO_STR(val
, spw
->sp_flag
);
880 NEW_ATTR(sattrs
, sidx
, _S_FLAG
, val
);
882 case ATTR_RST_FAILED_LOGINS
:
883 if (!ldapbuf
->shadow_update_enabled
) {
884 rc
= PWU_CHANGE_NOT_ALLOWED
;
885 break; /* not managing passwordAccount */
887 p
->data
.val_i
= spw
->sp_flag
& FAILCOUNT_MASK
;
888 spw
->sp_flag
&= ~FAILCOUNT_MASK
;
889 NUM_TO_STR(val
, spw
->sp_flag
);
890 NEW_ATTR(sattrs
, sidx
, _S_FLAG
, val
);
898 * If the ldap client is configured with shadow update enabled,
899 * then what should the new aging values look like?
901 * There are a number of different conditions
903 * a) aging is already configured: don't touch it
905 * b) disable_aging is set: disable aging
907 * c) aging is not configured: turn on default aging;
909 * b) and c) of course only if aging_needed and !aging_set.
910 * (i.e., password changed, and aging values not changed)
913 if (ldapbuf
->shadow_update_enabled
&& spw
!= NULL
&& spw
->sp_max
<= 0) {
914 /* a) aging not yet configured */
915 if (aging_needed
&& !aging_set
) {
917 /* b) turn off aging */
918 spw
->sp_min
= spw
->sp_max
= spw
->sp_warn
= -1;
919 if (attr_addmod(sattrs
, &sidx
, _S_MIN
, -1) < 0)
921 if (attr_addmod(sattrs
, &sidx
, _S_MAX
, -1) < 0)
923 if (attr_addmod(sattrs
, &sidx
, _S_WARNING
,
928 turn_on_default_aging(spw
);
930 if (attr_addmod(sattrs
, &sidx
, _S_MIN
,
933 if (attr_addmod(sattrs
, &sidx
, _S_MAX
,
936 if (attr_addmod(sattrs
, &sidx
,
937 _S_WARNING
, spw
->sp_warn
) < 0)
950 * ldap_to_pwu_code(error, pwd_status)
952 * translation from LDAP return values and PWU return values
955 ldap_to_pwu_code(int error
, int pwd_status
)
958 case NS_LDAP_SUCCESS
: return (PWU_SUCCESS
);
959 case NS_LDAP_OP_FAILED
: return (PWU_DENIED
);
960 case NS_LDAP_NOTFOUND
: return (PWU_NOT_FOUND
);
961 case NS_LDAP_MEMORY
: return (PWU_NOMEM
);
962 case NS_LDAP_CONFIG
: return (PWU_NOT_FOUND
);
963 case NS_LDAP_INTERNAL
:
964 switch (pwd_status
) {
965 case NS_PASSWD_EXPIRED
:
967 case NS_PASSWD_CHANGE_NOT_ALLOWED
:
968 return (PWU_CHANGE_NOT_ALLOWED
);
969 case NS_PASSWD_TOO_SHORT
:
970 return (PWU_PWD_TOO_SHORT
);
971 case NS_PASSWD_INVALID_SYNTAX
:
972 return (PWU_PWD_INVALID
);
973 case NS_PASSWD_IN_HISTORY
:
974 return (PWU_PWD_IN_HISTORY
);
975 case NS_PASSWD_WITHIN_MIN_AGE
:
976 return (PWU_WITHIN_MIN_AGE
);
978 return (PWU_SYSTEM_ERROR
);
980 default: return (PWU_SYSTEM_ERROR
);
985 ldap_replaceattr(const char *dn
, ns_ldap_attr_t
**attrs
, const char *binddn
,
986 const char *pwd
, int *pwd_status
, int flags
)
988 int result
= NS_LDAP_OP_FAILED
;
991 char **certpath
= NULL
;
993 ns_auth_t
**authpp
= NULL
;
994 ns_auth_t
*authp
= NULL
;
996 ns_ldap_error_t
*errorp
= NULL
;
998 debug("%s: replace_ldapattr()", __FILE__
);
1000 if ((credp
= (ns_cred_t
*)calloc(1, sizeof (ns_cred_t
))) == NULL
)
1001 return (NS_LDAP_MEMORY
); /* map to PWU_NOMEM */
1003 /* for admin shadow update, dn and pwd will be set later in libsldap */
1004 if ((flags
& NS_LDAP_UPDATE_SHADOW
) == 0) {
1005 /* Fill in the user name and password */
1006 if (dn
== NULL
|| pwd
== NULL
)
1008 credp
->cred
.unix_cred
.userID
= strdup(binddn
);
1009 credp
->cred
.unix_cred
.passwd
= strdup(pwd
);
1012 /* get host certificate path, if one is configured */
1013 ldaprc
= __ns_ldap_getParam(NS_LDAP_HOST_CERTPATH_P
,
1014 (void ***)&certpath
, &errorp
);
1015 if (ldaprc
!= NS_LDAP_SUCCESS
)
1018 if (certpath
&& *certpath
)
1019 credp
->hostcertpath
= *certpath
;
1021 /* Load the service specific authentication method */
1022 ldaprc
= __ns_ldap_getServiceAuthMethods("passwd-cmd", &authpp
,
1025 if (ldaprc
!= NS_LDAP_SUCCESS
)
1029 * if authpp is null, there is no serviceAuthenticationMethod
1030 * try default authenticationMethod
1032 if (authpp
== NULL
) {
1033 ldaprc
= __ns_ldap_getParam(NS_LDAP_AUTH_P
, (void ***)&authpp
,
1035 if (ldaprc
!= NS_LDAP_SUCCESS
)
1040 * if authpp is still null, then can not authenticate, syslog
1041 * error message and return error
1043 if (authpp
== NULL
) {
1045 "passwdutil: no legal LDAP authentication method configured");
1046 result
= NS_LDAP_OP_FAILED
;
1051 * Walk the array and try all authentication methods in order except
1054 for (app
= authpp
; *app
; app
++) {
1056 /* what about disabling other mechanisms? "tls:sasl/EXTERNAL" */
1057 if (authp
->type
== NS_LDAP_AUTH_NONE
)
1060 credp
->auth
.type
= authp
->type
;
1061 credp
->auth
.tlstype
= authp
->tlstype
;
1062 credp
->auth
.saslmech
= authp
->saslmech
;
1063 credp
->auth
.saslopt
= authp
->saslopt
;
1065 ldaprc
= __ns_ldap_repAttr("shadow", dn
,
1066 (const ns_ldap_attr_t
* const *)attrs
,
1067 credp
, flags
, &errorp
);
1068 if (ldaprc
== NS_LDAP_SUCCESS
) {
1069 result
= NS_LDAP_SUCCESS
;
1074 * if change not allowed due to configuration, indicate so
1077 if (ldaprc
== NS_LDAP_CONFIG
&&
1078 errorp
->status
== NS_CONFIG_NOTALLOW
) {
1079 result
= NS_LDAP_CONFIG
;
1080 *pwd_status
= NS_PASSWD_CHANGE_NOT_ALLOWED
;
1085 * other errors might need to be added to this list, for
1086 * the current supported mechanisms this is sufficient
1088 if ((ldaprc
== NS_LDAP_INTERNAL
) &&
1089 (errorp
->pwd_mgmt
.status
== NS_PASSWD_GOOD
) &&
1090 ((errorp
->status
== LDAP_INAPPROPRIATE_AUTH
) ||
1091 (errorp
->status
== LDAP_INVALID_CREDENTIALS
))) {
1097 * If there is error related to password policy,
1098 * return it to caller
1100 if ((ldaprc
== NS_LDAP_INTERNAL
) &&
1101 errorp
->pwd_mgmt
.status
!= NS_PASSWD_GOOD
) {
1102 *pwd_status
= errorp
->pwd_mgmt
.status
;
1106 *pwd_status
= NS_PASSWD_GOOD
;
1108 /* we don't really care about the error, just clean it up */
1110 (void) __ns_ldap_freeError(&errorp
);
1112 if (authstried
== 0) {
1114 "passwdutil: no legal LDAP authentication method configured");
1115 result
= NS_LDAP_CONFIG
;
1118 result
= NS_LDAP_OP_FAILED
; /* map to PWU_DENIED */
1122 (void) __ns_ldap_freeCred(&credp
);
1125 (void) __ns_ldap_freeParam((void ***)&authpp
);
1128 (void) __ns_ldap_freeError(&errorp
);
1135 * ldap_putpwnam(name, oldpw, rep, buf)
1137 * update the LDAP server with the attributes contained in 'buf'.
1141 ldap_putpwnam(char *name
, char *oldpw
, pwu_repository_t
*rep
, void *buf
)
1144 char *dn
; /* dn of user whose attributes we are changing */
1145 char *binddn
; /* dn of user who is performing the change */
1146 ns_ldap_error_t
*errorp
;
1147 ldapbuf_t
*ldapbuf
= (ldapbuf_t
*)buf
;
1148 ns_ldap_attr_t
**pattrs
= ldapbuf
->pattrs
;
1149 ns_ldap_attr_t
**sattrs
= ldapbuf
->sattrs
;
1154 if (strcmp(name
, "root") == 0)
1155 return (PWU_NOT_FOUND
);
1158 * convert name of user whose attributes we are changing
1159 * to a distinguished name
1161 res
= __ns_ldap_uid2dn(name
, &dn
, NULL
, &errorp
);
1162 if (res
!= NS_LDAP_SUCCESS
)
1165 /* update shadow via ldap_cachemgr if it is enabled */
1166 if (ldapbuf
->shadow_update_enabled
&&
1167 sattrs
!= NULL
&& sattrs
[0] != NULL
) {
1169 * flag NS_LDAP_UPDATE_SHADOW indicates the shadow update
1170 * should be done via ldap_cachemgr
1172 res
= ldap_replaceattr(dn
, sattrs
, NULL
, NULL
, &pwd_status
,
1173 NS_LDAP_UPDATE_SHADOW
);
1178 * The LDAP server checks whether we are permitted to perform
1179 * the requested change. We need to send the name of the user
1180 * who is executing this piece of code, together with his
1181 * current password to the server.
1182 * If this is executed by a normal user changing his/her own
1183 * password, this will simply be the OLD password that is to
1185 * Specific case if the user who is executing this piece
1186 * of code is root. We will then issue the LDAP request
1187 * with the DN of the user we want to change the passwd of.
1191 * create a dn for the user who is executing this code
1195 if ((pw
= getpwnam_from(name
, rep
, REP_LDAP
)) == NULL
) {
1196 res
= NS_LDAP_OP_FAILED
;
1199 } else if ((pw
= getpwuid_from(uid
, rep
, REP_LDAP
)) == NULL
) {
1201 * User executing this code is not known to the LDAP
1202 * server. This operation is to be denied
1204 res
= NS_LDAP_OP_FAILED
;
1208 res
= __ns_ldap_uid2dn(pw
->pw_name
, &binddn
, NULL
, &errorp
);
1209 if (res
!= NS_LDAP_SUCCESS
)
1212 if (pattrs
&& pattrs
[0] != NULL
) {
1213 res
= ldap_replaceattr(dn
, pattrs
, binddn
, oldpw
,
1216 res
= NS_LDAP_OP_FAILED
;
1219 free_ldapbuf(ldapbuf
);
1222 return (ldap_to_pwu_code(res
, pwd_status
));