summaryrefslogtreecommitdiffstats
path: root/system_cmds/chkpasswd.tproj
diff options
context:
space:
mode:
Diffstat (limited to 'system_cmds/chkpasswd.tproj')
-rw-r--r--system_cmds/chkpasswd.tproj/chkpasswd.859
-rw-r--r--system_cmds/chkpasswd.tproj/chkpasswd.pam5
-rw-r--r--system_cmds/chkpasswd.tproj/file_passwd.c276
-rw-r--r--system_cmds/chkpasswd.tproj/nis_passwd.c210
-rw-r--r--system_cmds/chkpasswd.tproj/od_passwd.c105
-rw-r--r--system_cmds/chkpasswd.tproj/pam_passwd.c81
-rw-r--r--system_cmds/chkpasswd.tproj/passwd.c174
-rw-r--r--system_cmds/chkpasswd.tproj/passwd.h5
-rw-r--r--system_cmds/chkpasswd.tproj/stringops.c261
-rw-r--r--system_cmds/chkpasswd.tproj/stringops.h39
10 files changed, 1215 insertions, 0 deletions
diff --git a/system_cmds/chkpasswd.tproj/chkpasswd.8 b/system_cmds/chkpasswd.tproj/chkpasswd.8
new file mode 100644
index 0000000..fd6c4f2
--- /dev/null
+++ b/system_cmds/chkpasswd.tproj/chkpasswd.8
@@ -0,0 +1,59 @@
+.Dd July 20, 2004
+.Dt CHKPASSWD 8
+.Os Darwin
+.Sh NAME
+.Nm chkpasswd
+.Nd verifies user password against various systems
+.Sh SYNOPSIS
+.Nm chkpasswd
+.Op Fl i Ar infosystem Op Fl l Ar location
+.Op Fl c
+.Op Ar name
+.Sh DESCRIPTION
+.Nm chkpasswd
+verifies a supplied username and password against file, NIS,
+or OpenDirectory infosystems.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.\" ==========
+.It Fl c
+The supplied password is compared verbatim without first being encrypted.
+.\" ==========
+.It Fl i Ar infosystem
+Specify the system against which to check the password
+(default is PAM). Valid systems:
+.Bl -tag -width "opendirectory"
+.It Ar file
+File-based passwords
+.It Ar nis
+NIS/YP authentication
+.It Ar opendirectory
+OpenDirectory (Directory Services) authentication.
+If no
+.Fl l
+option is specified, the search node is used.
+.It Ar PAM
+Pluggable Authentication Modules
+.El
+.Pp
+.\" ==========
+.It Fl l Ar location
+Specify a location; varies based on infosystem type:
+.Bl -tag -width "for opendirectory"
+.It for file
+Filename (default: /etc/master.passwd).
+.It for nis
+NIS domainname.
+.It for opendirectory
+A directory node name such as /Local/Default.
+.It for PAM
+Unused.
+.El
+.Pp
+.El
+.Ar name
+username
+.Sh SEE ALSO
+.Xr dscl 1 ,
+.Xr passwd 5
diff --git a/system_cmds/chkpasswd.tproj/chkpasswd.pam b/system_cmds/chkpasswd.tproj/chkpasswd.pam
new file mode 100644
index 0000000..18404e6
--- /dev/null
+++ b/system_cmds/chkpasswd.tproj/chkpasswd.pam
@@ -0,0 +1,5 @@
+# chkpasswd: auth account
+auth required pam_opendirectory.so
+account required pam_opendirectory.so
+password required pam_permit.so
+session required pam_permit.so
diff --git a/system_cmds/chkpasswd.tproj/file_passwd.c b/system_cmds/chkpasswd.tproj/file_passwd.c
new file mode 100644
index 0000000..90f54f2
--- /dev/null
+++ b/system_cmds/chkpasswd.tproj/file_passwd.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
+ * Reserved. This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License'). You may not use this file
+ * except in compliance with the License. Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <errno.h>
+#include <string.h>
+#include "stringops.h"
+
+#define TEMP_FILE "/tmp/.pwtmp"
+
+#define _PASSWD_FILE "/etc/master.passwd"
+#define _COMPAT_FILE "/etc/passwd"
+#define _PASSWD_FIELDS 10
+#define BUFSIZE 8192
+
+#include "passwd.h"
+
+static char *
+_getline(FILE *fp)
+{
+ static char s[BUFSIZE];
+ size_t len;
+
+ s[0] = '\0';
+
+ fgets(s, BUFSIZE, fp);
+ if (s[0] == '\0') return NULL;
+
+ if (s[0] == '#') return s;
+
+ len = strlen(s) - 1;
+ s[len] = '\0';
+
+ return s;
+}
+
+static struct passwd *
+parse_user(char *line)
+{
+ static struct passwd pw = {0};
+ char **tokens;
+ int i, len;
+
+ if (pw.pw_name != NULL) free(pw.pw_name);
+ pw.pw_name = NULL;
+ if (pw.pw_passwd != NULL) free(pw.pw_passwd);
+ pw.pw_passwd = NULL;
+ if (pw.pw_gecos != NULL) free(pw.pw_gecos);
+ pw.pw_gecos = NULL;
+ if (pw.pw_dir != NULL) free(pw.pw_dir);
+ pw.pw_dir = NULL;
+ if (pw.pw_shell != NULL) free(pw.pw_shell);
+ pw.pw_shell = NULL;
+
+ if (pw.pw_class != NULL) free(pw.pw_class);
+ pw.pw_class = NULL;
+
+ if (line == NULL) return (struct passwd *)NULL;
+ tokens = explode(line, ':');
+ len = listLength(tokens);
+
+ if (len != _PASSWD_FIELDS)
+ {
+ freeList(tokens);
+ return (struct passwd *)NULL;
+ }
+
+ i = 0;
+ pw.pw_name = tokens[i++];
+ pw.pw_passwd = tokens[i++];
+ pw.pw_uid = atoi(tokens[i]);
+ free(tokens[i++]);
+ pw.pw_gid = atoi(tokens[i]);
+ free(tokens[i++]);
+ pw.pw_class = tokens[i++];
+ pw.pw_change = atoi(tokens[i]);
+ free(tokens[i++]);
+ pw.pw_expire = atoi(tokens[i]);
+ free(tokens[i++]);
+ pw.pw_gecos = tokens[i++];
+ pw.pw_dir = tokens[i++];
+ pw.pw_shell = tokens[i++];
+
+ return &pw;
+}
+
+static struct passwd *
+find_user(char *uname, FILE *fp)
+{
+ char *line;
+ struct passwd *pw;
+
+ rewind(fp);
+
+ while (NULL != (line = _getline(fp)))
+ {
+ if (line[0] == '#') continue;
+ pw = parse_user(line);
+ if (pw == (struct passwd *)NULL) continue;
+ if (!strcmp(uname, pw->pw_name)) return pw;
+ }
+
+ pw = parse_user(NULL);
+ return (struct passwd *)NULL;
+}
+
+#if 0
+static void
+rewrite_file(char *pwname, FILE *fp, struct passwd *newpw)
+{
+ char *line;
+ struct passwd *pw;
+ FILE *tfp, *cfp;
+ char fname[256];
+
+ sprintf(fname, "%s.%d", TEMP_FILE, getpid());
+
+ tfp = fopen(fname, "w+");
+ if (tfp == NULL)
+ {
+ fprintf(stderr, "can't write temporary file \"%s\": ", fname);
+ perror("");
+ exit(1);
+ }
+
+ cfp = NULL;
+ if (!strcmp(pwname, _PASSWD_FILE))
+ {
+ cfp = fopen(_COMPAT_FILE, "w");
+ if (cfp == NULL)
+ {
+ fprintf(stderr, "warning: can't write compatability file \"%s\": ",
+ _COMPAT_FILE);
+ perror("");
+ }
+ }
+
+ if (cfp != NULL)
+ {
+ fprintf(cfp, "#\n");
+ fprintf(cfp, "# 4.3BSD-compatable User Database\n");
+ fprintf(cfp, "#\n");
+ fprintf(cfp, "# Note that this file is not consulted for login.\n");
+ fprintf(cfp, "# It only exisits for compatability with 4.3BSD utilities.\n");
+ fprintf(cfp, "#\n");
+ fprintf(cfp, "# This file is automatically re-written by various system utilities.\n");
+ fprintf(cfp, "# Do not edit this file. Changes will be lost.\n");
+ fprintf(cfp, "#\n");
+ }
+
+ rewind(fp);
+
+ while (NULL != (line = _getline(fp)))
+ {
+ if (line[0] == '#')
+ {
+ fprintf(tfp, "%s", line);
+ continue;
+ }
+
+ pw = parse_user(line);
+ if (pw == (struct passwd *)NULL)
+ {
+ fprintf(stderr, "warning: bad format for entry: \"%s\"\n", line);
+ fprintf(tfp, "%s\n", line);
+ if (cfp != NULL) fprintf(cfp, "%s\n", line);
+ continue;
+ }
+
+ if (strcmp(newpw->pw_name, pw->pw_name))
+ {
+ fprintf(tfp, "%s\n", line);
+ if (cfp != NULL) fprintf(cfp, "%s\n", line);
+ continue;
+ }
+
+ fprintf(tfp, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
+ newpw->pw_name, newpw->pw_passwd, newpw->pw_uid, newpw->pw_gid,
+ newpw->pw_class, newpw->pw_change, newpw->pw_expire,
+ newpw->pw_gecos, newpw->pw_dir, newpw->pw_shell);
+ if (cfp != NULL)
+ {
+ fprintf(cfp, "%s:",newpw->pw_name);
+ if ((newpw->pw_passwd == NULL) || (newpw->pw_passwd[0] == '\0'))
+ fprintf(cfp, ":");
+ else
+ fprintf(cfp, "*:");
+ fprintf(cfp, "%d:%d:%s:%s:%s\n",
+ newpw->pw_uid, newpw->pw_gid, newpw->pw_gecos,
+ newpw->pw_dir, newpw->pw_shell);
+ }
+ }
+
+ if (cfp != NULL) fclose(cfp);
+ fclose(fp);
+ if (unlink(pwname) < 0)
+ {
+ fprintf(stderr, "can't update \"%s\": ", pwname);
+ perror("");
+ }
+
+ rewind(tfp);
+
+ fp = fopen(pwname, "w");
+ if (fp == NULL)
+ {
+ fprintf(stderr, "ERROR: lost file \"%s\"\n", pwname);
+ fprintf(stderr, "new passwd file is \"%s\"\n", fname);
+ perror("open");
+ exit(1);
+ }
+
+ while (NULL != (line = _getline(tfp)))
+ {
+ fprintf(fp, "%s", line);
+ if (line[0] != '#') fprintf(fp, "\n");
+ }
+ fclose(fp);
+ fclose(tfp);
+ unlink(fname);
+}
+#endif /* 0 */
+
+int
+file_check_passwd(char *uname, char *locn)
+{
+ FILE *fp;
+ char *fname;
+ struct passwd *pw;
+
+ fname = _PASSWD_FILE;
+ if (locn != NULL) fname = locn;
+
+ if (access(fname,R_OK) || (fp = fopen(fname, "r")) == NULL)
+ {
+ fprintf(stderr, "can't read file \"%s\": ", fname);
+ perror("");
+ exit(1);
+ }
+
+
+ pw = find_user(uname, fp);
+ if (pw == (struct passwd *)NULL)
+ {
+ fprintf(stderr, "user %s not found in file %s\n", uname, fname);
+ exit(1);
+ }
+
+ checkpasswd(uname, pw->pw_passwd);
+ fclose(fp);
+
+ return 0;
+}
diff --git a/system_cmds/chkpasswd.tproj/nis_passwd.c b/system_cmds/chkpasswd.tproj/nis_passwd.c
new file mode 100644
index 0000000..c2e6e4f
--- /dev/null
+++ b/system_cmds/chkpasswd.tproj/nis_passwd.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
+ * Reserved. This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License'). You may not use this file
+ * except in compliance with the License. Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1998 by Apple Computer, Inc.
+ * Portions Copyright (c) 1988 by Sun Microsystems, Inc.
+ * Portions Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/* update a user's password in NIS. This was based on the Sun implementation
+ * we used in NEXTSTEP, although I've added some stuff from OpenBSD. And
+ * it uses the API to support Rhapsody's proprietry infosystem switch.
+ * lukeh
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <pwd.h>
+#include <netinet/in.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_clnt.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/yppasswd.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <errno.h>
+
+#include "passwd.h"
+
+static struct passwd *ypgetpwnam(char *name, char *domain);
+
+int
+nis_check_passwd(char *uname, char *domain)
+{
+ int port;
+ char *master;
+ struct passwd *pwd;
+
+ if (domain == NULL)
+ {
+ if (yp_get_default_domain(&domain) != 0)
+ {
+ (void)fprintf(stderr, "can't get domain\n");
+ exit(1);
+ }
+ }
+
+ if (yp_master(domain, "passwd.byname", &master) != 0)
+ {
+ (void)fprintf(stderr, "can't get master for passwd file\n");
+ exit(1);
+ }
+
+ port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE,
+ IPPROTO_UDP);
+ if (port == 0)
+ {
+ (void)fprintf(stderr, "%s is not running yppasswd daemon\n",
+ master);
+ exit(1);
+ }
+ if (port >= IPPORT_RESERVED)
+ {
+ (void)fprintf(stderr,
+ "yppasswd daemon is not running on privileged port\n");
+ exit(1);
+ }
+
+ pwd = ypgetpwnam(uname, domain);
+ if (pwd == NULL)
+ {
+ (void)fprintf(stderr, "user %s not found\n", uname);
+ exit(1);
+ }
+
+ checkpasswd(uname, pwd->pw_passwd);
+ return(0);
+}
+
+static char *
+pwskip(register char *p)
+{
+ while (*p && *p != ':' && *p != '\n')
+ ++p;
+ if (*p)
+ *p++ = 0;
+ return (p);
+}
+
+static struct passwd *
+interpret(struct passwd *pwent, char *line)
+{
+ register char *p = line;
+
+ pwent->pw_passwd = "*";
+ pwent->pw_uid = 0;
+ pwent->pw_gid = 0;
+ pwent->pw_gecos = "";
+ pwent->pw_dir = "";
+ pwent->pw_shell = "";
+#ifndef __SLICK__
+ pwent->pw_change = 0;
+ pwent->pw_expire = 0;
+ pwent->pw_class = "";
+#endif
+
+ /* line without colon separators is no good, so ignore it */
+ if(!strchr(p, ':'))
+ return(NULL);
+
+ pwent->pw_name = p;
+ p = pwskip(p);
+ pwent->pw_passwd = p;
+ p = pwskip(p);
+ pwent->pw_uid = (uid_t)strtoul(p, NULL, 10);
+ p = pwskip(p);
+ pwent->pw_gid = (gid_t)strtoul(p, NULL, 10);
+ p = pwskip(p);
+ pwent->pw_gecos = p;
+ p = pwskip(p);
+ pwent->pw_dir = p;
+ p = pwskip(p);
+ pwent->pw_shell = p;
+ while (*p && *p != '\n')
+ p++;
+ *p = '\0';
+ return (pwent);
+}
+
+static struct passwd *
+ypgetpwnam(char *nam, char *domain)
+{
+ static struct passwd pwent;
+ char *val;
+ int reason, vallen;
+ static char *__yplin = NULL;
+
+ reason = yp_match(domain, "passwd.byname", nam, (int)strlen(nam),
+ &val, &vallen);
+ switch(reason) {
+ case 0:
+ break;
+ default:
+ return (NULL);
+ break;
+ }
+ val[vallen] = '\0';
+ if (__yplin)
+ free(__yplin);
+ __yplin = (char *)malloc(vallen + 1);
+ strcpy(__yplin, val);
+ free(val);
+
+ return(interpret(&pwent, __yplin));
+}
diff --git a/system_cmds/chkpasswd.tproj/od_passwd.c b/system_cmds/chkpasswd.tproj/od_passwd.c
new file mode 100644
index 0000000..2ea724f
--- /dev/null
+++ b/system_cmds/chkpasswd.tproj/od_passwd.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1998-2016 Apple Inc. All rights reserved.
+ * Portions Copyright (c) 1988 by Sun Microsystems, Inc.
+ * Portions Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <pwd.h>
+#include <netinet/in.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/yppasswd.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <errno.h>
+
+#include <OpenDirectory/OpenDirectory.h>
+
+#include "passwd.h"
+
+//-------------------------------------------------------------------------------------
+// od_check_passwd
+//-------------------------------------------------------------------------------------
+
+int
+od_check_passwd(const char *uname, const char *domain)
+{
+ int authenticated = 0;
+
+ ODSessionRef session = NULL;
+ ODNodeRef node = NULL;
+ ODRecordRef rec = NULL;
+ CFStringRef user = NULL;
+ CFStringRef location = NULL;
+ CFStringRef password = NULL;
+
+ if (uname) user = CFStringCreateWithCString(NULL, uname, kCFStringEncodingUTF8);
+ if (domain) location = CFStringCreateWithCString(NULL, domain, kCFStringEncodingUTF8);
+
+ if (user) {
+ printf("Checking password for %s.\n", uname);
+ char* p = getpass("Password:");
+ if (p) password = CFStringCreateWithCString(NULL, p, kCFStringEncodingUTF8);
+ }
+
+ if (password) {
+ session = ODSessionCreate(NULL, NULL, NULL);
+ if (session) {
+ if (location) {
+ node = ODNodeCreateWithName(NULL, session, location, NULL);
+ } else {
+ node = ODNodeCreateWithNodeType(NULL, session, kODNodeTypeAuthentication, NULL);
+ }
+ if (node) {
+ rec = ODNodeCopyRecord(node, kODRecordTypeUsers, user, NULL, NULL);
+ }
+ if (rec) {
+ authenticated = ODRecordVerifyPassword(rec, password, NULL);
+ }
+ }
+ }
+
+ if (!authenticated) {
+ fprintf(stderr, "Sorry\n");
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/system_cmds/chkpasswd.tproj/pam_passwd.c b/system_cmds/chkpasswd.tproj/pam_passwd.c
new file mode 100644
index 0000000..07d9919
--- /dev/null
+++ b/system_cmds/chkpasswd.tproj/pam_passwd.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+#include <security/pam_appl.h>
+#include <security/openpam.h> /* for openpam_ttyconv() */
+
+#include "passwd.h"
+
+extern char* progname;
+static pam_handle_t *pamh;
+static struct pam_conv pamc;
+
+//-------------------------------------------------------------------------------------
+// pam_check_passwd
+//-------------------------------------------------------------------------------------
+
+int
+pam_check_passwd(char* uname)
+{
+ int retval = PAM_SUCCESS;
+
+ /* Initialize PAM. */
+ pamc.conv = &openpam_ttyconv;
+ pam_start(progname, uname, &pamc, &pamh);
+
+ printf("Checking password for %s.\n", uname);
+
+ /* Authenticate. */
+ if (PAM_SUCCESS != (retval = pam_authenticate(pamh, 0)))
+ goto pamerr;
+
+ /* Authorize. */
+ if (PAM_SUCCESS != (retval = pam_acct_mgmt(pamh, 0)) && PAM_NEW_AUTHTOK_REQD != retval)
+ goto pamerr;
+
+ /* Change the password. */
+ if (PAM_NEW_AUTHTOK_REQD == retval && PAM_SUCCESS != (retval = pam_chauthtok(pamh, 0)))
+ goto pamerr;
+
+ /* Set the credentials. */
+ if (PAM_SUCCESS != (retval = pam_setcred(pamh, PAM_ESTABLISH_CRED)))
+ goto pamerr;
+
+ /* Open the session. */
+ if (PAM_SUCCESS != (retval = pam_open_session(pamh, 0)))
+ goto pamerr;
+
+ /* Close the session. */
+ if (PAM_SUCCESS != (retval = pam_close_session(pamh, 0)))
+ goto pamerr;
+
+pamerr:
+ /* Print an error, if needed. */
+ if (PAM_SUCCESS != retval)
+ fprintf(stderr, "Sorry\n");
+
+ /* Terminate PAM. */
+ pam_end(pamh, retval);
+ return retval;
+}
diff --git a/system_cmds/chkpasswd.tproj/passwd.c b/system_cmds/chkpasswd.tproj/passwd.c
new file mode 100644
index 0000000..bff8280
--- /dev/null
+++ b/system_cmds/chkpasswd.tproj/passwd.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
+ * Reserved. This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License'). You may not use this file
+ * except in compliance with the License. Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#define INFO_FILE 1
+#define INFO_NIS 2
+#define INFO_OPEN_DIRECTORY 3
+#define INFO_PAM 4
+
+#ifndef __SLICK__
+#define _PASSWD_FILE "/etc/master.passwd"
+#else
+#define _PASSWD_FILE "/etc/passwd"
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <pwd.h>
+#include <libc.h>
+#include <ctype.h>
+#include <string.h>
+#include <pwd.h>
+#include "stringops.h"
+
+#ifdef __SLICK__
+#define _PASSWORD_LEN 8
+#endif
+
+#include "passwd.h"
+
+const char* progname = "chkpasswd";
+
+static int literal = 0;
+
+void
+checkpasswd(char *name, char *old_pw)
+{
+ int isNull;
+ char *p;
+
+ printf("Checking password for %s.\n", name);
+
+ p = "";
+ isNull = 0;
+ if (old_pw == NULL) isNull = 1;
+ if ((isNull == 0) && (old_pw[0] == '\0')) isNull = 1;
+ if (isNull == 0)
+ {
+ p = getpass("Password:");
+ sleep(1); // make sure this doesn't go too quickly
+ if (strcmp(literal ? p : crypt(p, old_pw), old_pw))
+ {
+ errno = EACCES;
+ fprintf(stderr, "Sorry\n");
+ exit(1);
+ }
+ }
+ return;
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: chkpasswd [-i infosystem] [-l location] [-c] [name]\n");
+ fprintf(stderr, " infosystem:\n");
+ fprintf(stderr, " file\n");
+ fprintf(stderr, " NIS\n");
+ fprintf(stderr, " OpenDirectory\n");
+ fprintf(stderr, " location (for infosystem):\n");
+ fprintf(stderr, " file location is path to file (default is %s)\n", _PASSWD_FILE);
+ fprintf(stderr, " NIS location is NIS domain name\n");
+ fprintf(stderr, " OpenDirectory location is directory node name\n");
+ fprintf(stderr, " -c: supplied password is compared verbatim without first\n");
+ fprintf(stderr, " being crypted\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char* user = NULL;
+ char* locn = NULL;
+ int infosystem, ch;
+
+ infosystem = INFO_PAM;
+
+ while ((ch = getopt(argc, argv, "ci:l:")) != -1) {
+ switch(ch) {
+ case 'i':
+ if (!strcasecmp(optarg, "file")) {
+ infosystem = INFO_FILE;
+ } else if (!strcasecmp(optarg, "NIS")) {
+ infosystem = INFO_NIS;
+ } else if (!strcasecmp(optarg, "YP")) {
+ infosystem = INFO_NIS;
+ } else if (!strcasecmp(optarg, "opendirectory")) {
+ infosystem = INFO_OPEN_DIRECTORY;
+ } else if (!strcasecmp(optarg, "PAM")) {
+ infosystem = INFO_PAM;
+ } else {
+ fprintf(stderr, "%s: Unknown info system \'%s\'.\n",
+ progname, optarg);
+ usage();
+ }
+ break;
+ case 'l':
+ locn = optarg;
+ break;
+ case 'c':
+ literal++;
+ break;
+ case '?':
+ default:
+ usage();
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 1) {
+ usage();
+ } else if (argc == 1) {
+ user = argv[0];
+ }
+
+ if (user == NULL) {
+ struct passwd* pw = getpwuid(getuid());
+ if (pw != NULL && pw->pw_name != NULL) {
+ user = strdup(pw->pw_name);
+ }
+ if (user == NULL) {
+ fprintf(stderr, "you don't have a login name\n");
+ exit(1);
+ }
+ }
+
+ switch (infosystem)
+ {
+ case INFO_FILE:
+ file_check_passwd(user, locn);
+ break;
+ case INFO_NIS:
+ nis_check_passwd(user, locn);
+ break;
+ case INFO_OPEN_DIRECTORY:
+ od_check_passwd(user, locn);
+ break;
+ case INFO_PAM:
+ pam_check_passwd(user);
+ break;
+ }
+
+ exit(0);
+}
diff --git a/system_cmds/chkpasswd.tproj/passwd.h b/system_cmds/chkpasswd.tproj/passwd.h
new file mode 100644
index 0000000..692722b
--- /dev/null
+++ b/system_cmds/chkpasswd.tproj/passwd.h
@@ -0,0 +1,5 @@
+int file_check_passwd(char *, char *);
+int nis_check_passwd(char *, char *);
+int od_check_passwd(const char *, const char *);
+int pam_check_passwd(char *);
+void checkpasswd(char *, char *);
diff --git a/system_cmds/chkpasswd.tproj/stringops.c b/system_cmds/chkpasswd.tproj/stringops.c
new file mode 100644
index 0000000..960ce19
--- /dev/null
+++ b/system_cmds/chkpasswd.tproj/stringops.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
+ * Reserved. This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License'). You may not use this file
+ * except in compliance with the License. Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#import <string.h>
+#import <stdlib.h>
+#import <stdio.h>
+#import <stdarg.h>
+#import "stringops.h"
+
+char *
+copyString(char *s)
+{
+ size_t len;
+ char *t;
+
+ if (s == NULL) return NULL;
+
+ len = strlen(s) + 1;
+ t = malloc(len);
+ bcopy(s, t, len);
+ return t;
+}
+
+char *
+concatString(char *s, char *t)
+{
+ size_t len;
+
+ if (t == NULL) return s;
+
+ len = strlen(s) + strlen(t) + 1;
+ s = realloc(s, len);
+ strcat(s, t);
+ return s;
+}
+
+char **
+insertString(char *s, char **l, unsigned int x)
+{
+ int i, len;
+
+ if (s == NULL) return l;
+ if (l == NULL)
+ {
+ l = (char **)malloc(2 * sizeof(char *));
+ l[0] = copyString(s);
+ l[1] = NULL;
+ return l;
+ }
+
+ for (i = 0; l[i] != NULL; i++);
+ len = i + 1; /* count the NULL on the end of the list too! */
+
+ l = (char **)realloc(l, (len + 1) * sizeof(char *));
+
+ if ((x >= (len - 1)) || (x == IndexNull))
+ {
+ l[len - 1] = copyString(s);
+ l[len] = NULL;
+ return l;
+ }
+
+ for (i = len; i > x; i--) l[i] = l[i - 1];
+ l[x] = copyString(s);
+ return l;
+}
+
+char **
+appendString(char *s, char **l)
+{
+ return insertString(s, l, IndexNull);
+}
+
+void
+freeList(char **l)
+{
+ int i;
+
+ if (l == NULL) return;
+ for (i = 0; l[i] != NULL; i++)
+ {
+ if (l[i] != NULL) free(l[i]);
+ l[i] = NULL;
+ }
+ if (l != NULL) free(l);
+}
+
+void
+freeString(char *s)
+{
+ if (s == NULL) return;
+ free(s);
+}
+
+unsigned int
+listLength(char **l)
+{
+ int i;
+
+ if (l == NULL) return 0;
+ for (i = 0; l[i] != NULL; i++);
+ return i;
+}
+
+unsigned int
+listIndex(char *s,char **l)
+{
+ int i;
+
+ if (l == NULL) return IndexNull;
+ for (i = 0; l[i] != NULL; i++)
+ {
+ if (strcmp(s, l[i]) == 0) return i;
+ }
+ return IndexNull;
+}
+
+char *
+prefix(char *s, char c)
+{
+ int i;
+ char *t;
+
+ if (s == NULL) return NULL;
+
+ for (i = 0; ((s[i] != '\0') && (s[i] != c)); i++);
+ if (i == 0) return NULL;
+ if (s[i] == '\0') return copyString(s);
+
+ t = malloc(i + 1);
+ bcopy(s, t, i);
+ t[i] = '\0';
+ return t;
+}
+
+char *
+postfix(char *s, char c)
+{
+ int i;
+ size_t len;
+ char *t;
+
+ if (s == NULL) return NULL;
+
+ for (i = 0; ((s[i] != '\0') && (s[i] != c)); i++);
+ if (s[i] == '\0') return NULL;
+ len = strlen(s) - i;
+ if (len == 1) return NULL;
+
+ t = malloc(len);
+ len--;
+ bcopy((s + i + 1), t, len);
+ t[len] = '\0';
+ return t;
+}
+
+char *
+presuffix(char *s, char c)
+{
+ ssize_t i;
+ size_t len;
+ char *t;
+
+ if (s == NULL) return NULL;
+
+ len = strlen(s);
+ for (i = len - 1; ((i >= 0) && (s[i] != c)); i--);
+ if (i == 0) return NULL;
+ if (s[0] == '\0') return NULL;
+
+ t = malloc(i + 1);
+ bcopy(s, t, i);
+ t[i] = '\0';
+ return t;
+}
+
+char *
+suffix(char *s, char c)
+{
+ ssize_t i;
+ size_t len;
+ char *t;
+
+ if (s == NULL) return NULL;
+
+ len = strlen(s);
+ for (i = len - 1; ((i >= 0) && (s[i] != c)); i--);
+ if (i == 0) return NULL;
+ len -= i;
+ if (len == 1) return NULL;
+ t = malloc(len);
+ len--;
+ bcopy((s + i + 1), t, len);
+ t[len] = '\0';
+ return t;
+}
+
+char *
+lowerCase(char *s)
+{
+ int i;
+ char *t;
+
+ if (s == NULL) return NULL;
+ t = malloc(strlen(s) + 1);
+
+ for (i = 0; s[i] != '\0'; i++)
+ {
+ if ((s[i] >= 'A') && (s[i] <= 'Z')) t[i] = s[i] + 32;
+ else t[i] = s[i];
+ }
+ t[i] = '\0';
+ return t;
+}
+
+char **
+explode(char *s, char c)
+{
+ char **l = NULL;
+ char *p, *t;
+ int i, n;
+
+ if (s == NULL) return NULL;
+
+ p = s;
+ while (p[0] != '\0')
+ {
+ for (i = 0; ((p[i] != '\0') && p[i] != c); i++);
+ n = i;
+ t = malloc(n + 1);
+ for (i = 0; i < n; i++) t[i] = p[i];
+ t[n] = '\0';
+ l = appendString(t, l);
+ free(t);
+ t = NULL;
+ if (p[i] == '\0') return l;
+ if (p[i + 1] == '\0') l = appendString("", l);
+ p = p + i + 1;
+ }
+ return l;
+}
diff --git a/system_cmds/chkpasswd.tproj/stringops.h b/system_cmds/chkpasswd.tproj/stringops.h
new file mode 100644
index 0000000..776adf6
--- /dev/null
+++ b/system_cmds/chkpasswd.tproj/stringops.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
+ * Reserved. This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License'). You may not use this file
+ * except in compliance with the License. Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#define streq(A, B) (strcmp(A, B) == 0)
+#define IndexNull (unsigned int)-1
+char *copyString(char *);
+char *concatString(char *, char *);
+char **insertString(char *, char **, unsigned int);
+char **appendString(char *, char **);
+void freeList(char **);
+void freeString(char *);
+unsigned int listLength(char **);
+unsigned int listIndex(char *,char **);
+char *prefix(char *, char);
+char *postfix(char *, char);
+char *presuffix(char *, char);
+char *suffix(char *, char);
+char *lowerCase(char *);
+char **explode(char *, char);