Commit 5526f82e authored by Quanah Gibson-Mount's avatar Quanah Gibson-Mount
Browse files

Sync up nssov

parent d813ab31
......@@ -32,7 +32,7 @@ all: nssov.la
XOBJS = tio.lo
OBJS = alias.lo ether.lo group.lo host.lo netgroup.lo network.lo \
nssov.lo passwd.lo protocol.lo rpc.lo service.lo shadow.lo
nssov.lo passwd.lo protocol.lo rpc.lo service.lo shadow.lo pam.lo
.SUFFIXES: .c .o .lo
......
Copyright 2008 Howard Chu, Symas Corp. All rights reserved.
Copyright 2008-2009 Howard Chu, Symas Corp. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted only as authorized by the OpenLDAP
......@@ -11,7 +11,8 @@ top-level directory of the distribution or, alternatively, at
This directory contains a slapd overlay, nssov, that handles
NSS lookup requests through a local Unix Domain socket. It uses the
same IPC protocol as Arthur de Jong's nss-ldapd, and a complete
copy of the nss-ldapd source is included here.
copy of the nss-ldapd source is included here. It also handles
PAM requests.
To use this code, you will need the client-side stub library from
nss-ldapd (which resides in nss-ldapd/nss). You will not need the
......@@ -38,7 +39,7 @@ use RFC2307bis.)
The overlay may be configured with Service Search Descriptors (SSDs)
for each NSS service that will be used. SSDs are configured using
nssov-svc <service> <url>
nssov-ssd <service> <url>
where the <service> may be one of
alias
......@@ -75,8 +76,51 @@ of the config entry is
objectClass: olcOverlayConfig
objectClass: olcNssOvConfig
olcOverlay: {0}nssov
olcNssSvc: passwd ldap:///ou=users,dc=example,dc=com??one
olcNssSsd: passwd ldap:///ou=users,dc=example,dc=com??one
olcNssMap: passwd uid accountName
which enables the passwd service, and uses the accountName attribute to
fetch what is usually retrieved from the uid attribute.
PAM authentication, account management, session management, and password
management are supported.
Authentication is performed using Simple Binds. Since all operations occur
inside the slapd overlay, "fake" connections are used and they are
inherently secure. Two methods of mapping the PAM username to an LDAP DN
are provided:
the mapping can be accomplished using slapd's authz-regexp facility. In
this case, a DN of the form
cn=<service>+uid=<user>,cn=<hostname>,cn=pam,cn=auth
is fed into the regexp matcher. If a match is produced, the resulting DN
is used.
otherwise, the NSS passwd map is invoked (which means it must already
be configured).
If no DN is found, the overlay returns PAM_USER_UNKNOWN. If the DN is
found, and Password Policy is supported, then the Bind will use the
Password Policy control and return expiration information to PAM.
Account management also uses two methods. These methods depend on the
ldapns.schema included with the nssov source.
The first is identical to the method used in PADL's pam_ldap module:
host and authorizedService attributes may be looked up in the user's entry,
and checked to determine access. Also a check may be performed to see if
the user is a member of a particular group. This method is pretty
inflexible and doesn't scale well to large networks of users, hosts,
and services.
The second uses slapd's ACL engine to check if the user has "compare"
privilege on an ipHost object whose name matches the current hostname, and
whose authorizedService attribute matches the current service name. This
method is preferred, since it allows authorization to be centralized in
the ipHost entries instead of scattered across the entire user population.
The ipHost entries must have an authorizedService attribute (e.g. by way
of the authorizedServiceObject auxiliary class) to use this method.
Session management: the overlay may optionally add a "logged in" attribute
to a user's entry for successful logins, and delete the corresponding
value upon logout. The attribute value is of the form
<generalizedTime> <host> <service> <tty> (<ruser@rhost>)
Password management: the overlay will perform a PasswordModify exop
in the server for the given user.
......@@ -58,7 +58,7 @@ static int write_alias(nssov_alias_cbp *cbp,Entry *entry)
a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[0].an_desc);
if ( !a )
{
Debug(LDAP_DEBUG_ANY,"alias entry %s does not contain %s value",
Debug(LDAP_DEBUG_ANY,"alias entry %s does not contain %s value\n",
entry->e_name.bv_val,cbp->mi->mi_attrs[0].an_desc->ad_cname.bv_val,0 );
return 0;
}
......@@ -98,7 +98,7 @@ NSSOV_HANDLE(
READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));
cbp.name.bv_len = tmpint32;
cbp.name.bv_val = cbp.buf;,
Debug(LDAP_DEBUG_TRACE,"nssov_alias_byname(%s)",cbp.name.bv_val,0,0);,
Debug(LDAP_DEBUG_TRACE,"nssov_alias_byname(%s)\n",cbp.name.bv_val,0,0);,
NSLCD_ACTION_ALIAS_BYNAME,
nssov_filter_byname(cbp.mi,0,&cbp.name,&filter)
)
......@@ -108,7 +108,7 @@ NSSOV_HANDLE(
struct berval filter;
/* no parameters to read */
BER_BVZERO(&cbp.name);,
Debug(LDAP_DEBUG,"nssov_alias_all()",0,0,0);,
Debug(LDAP_DEBUG,"nssov_alias_all()\n",0,0,0);,
NSLCD_ACTION_ALIAS_ALL,
(filter=cbp.mi->mi_filter,0)
)
......@@ -74,7 +74,7 @@ static int write_ether(nssov_ether_cbp *cbp,Entry *entry)
a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[0].an_desc);
if ( !a )
{
Debug(LDAP_DEBUG_ANY,"ether entry %s does not contain %s value",
Debug(LDAP_DEBUG_ANY,"ether entry %s does not contain %s value\n",
entry->e_name.bv_val,cbp->mi->mi_attrs[0].an_desc->ad_cname.bv_val,0 );
return 0;
}
......@@ -92,7 +92,7 @@ static int write_ether(nssov_ether_cbp *cbp,Entry *entry)
a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[1].an_desc);
if ( !a )
{
Debug(LDAP_DEBUG_ANY,"ether entry %s does not contain %s value",
Debug(LDAP_DEBUG_ANY,"ether entry %s does not contain %s value\n",
entry->e_name.bv_val,cbp->mi->mi_attrs[1].an_desc->ad_cname.bv_val,0 );
return 0;
}
......@@ -127,7 +127,7 @@ NSSOV_HANDLE(
READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));
cbp.name.bv_len = tmpint32;
cbp.name.bv_val = cbp.buf;,
Debug(LDAP_DEBUG_TRACE,"nssov_ether_byname(%s)",cbp.name.bv_val,0,0);,
Debug(LDAP_DEBUG_TRACE,"nssov_ether_byname(%s)\n",cbp.name.bv_val,0,0);,
NSLCD_ACTION_ETHER_BYNAME,
nssov_filter_byname(cbp.mi,0,&cbp.name,&filter)
)
......@@ -148,7 +148,7 @@ NSSOV_HANDLE(
addr.ether_addr_octet[4],
addr.ether_addr_octet[5]);
cbp.addr.bv_val = cbp.buf;,
Debug(LDAP_DEBUG_TRACE,"nssov_ether_byether(%s)",cbp.addr.bv_val,0,0);,
Debug(LDAP_DEBUG_TRACE,"nssov_ether_byether(%s)\n",cbp.addr.bv_val,0,0);,
NSLCD_ACTION_ETHER_BYETHER,
nssov_filter_byid(cbp.mi,1,&cbp.addr,&filter)
)
......@@ -159,7 +159,7 @@ NSSOV_HANDLE(
/* no parameters to read */
BER_BVZERO(&cbp.name);
BER_BVZERO(&cbp.addr);,
Debug(LDAP_DEBUG_TRACE,"nssov_ether_all()",0,0,0);,
Debug(LDAP_DEBUG_TRACE,"nssov_ether_all()\n",0,0,0);,
NSLCD_ACTION_ETHER_ALL,
(filter=cbp.mi->mi_filter,0)
)
/* group.c - group lookup routines */
/* $OpenLDAP$ */
/*
* Copyright 2008 by Howard Chu, Symas Corp.
* Copyright 2008-2009 by Howard Chu, Symas Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -121,6 +121,10 @@ static int isvalidgroupname(struct berval *name)
/* check other characters */
for (i=1;i<name->bv_len;i++)
{
#ifndef STRICT_GROUPS
/* allow spaces too */
if (name->bv_val[i] == ' ') continue;
#endif
if ( ! ( (name->bv_val[i]>='A' && name->bv_val[i] <= 'Z') ||
(name->bv_val[i]>='a' && name->bv_val[i] <= 'z') ||
(name->bv_val[i]>='0' && name->bv_val[i] <= '9') ||
......@@ -145,7 +149,7 @@ static int write_group(nssov_group_cbp *cbp,Entry *entry)
a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[CN_KEY].an_desc);
if ( !a )
{
Debug(LDAP_DEBUG_ANY,"group entry %s does not contain %s value",
Debug(LDAP_DEBUG_ANY,"group entry %s does not contain %s value\n",
entry->e_name.bv_val, cbp->mi->mi_attrs[CN_KEY].an_desc->ad_cname.bv_val,0);
return 0;
}
......@@ -163,7 +167,7 @@ static int write_group(nssov_group_cbp *cbp,Entry *entry)
a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[GID_KEY].an_desc);
if ( !a )
{
Debug(LDAP_DEBUG_ANY,"group entry %s does not contain %s value",
Debug(LDAP_DEBUG_ANY,"group entry %s does not contain %s value\n",
entry->e_name.bv_val, cbp->mi->mi_attrs[GID_KEY].an_desc->ad_cname.bv_val,0);
return 0;
}
......@@ -225,7 +229,7 @@ static int write_group(nssov_group_cbp *cbp,Entry *entry)
{
if (!isvalidgroupname(&names[i]))
{
Debug(LDAP_DEBUG_ANY,"nssov: group entry %s contains invalid group name: \"%s\"",
Debug(LDAP_DEBUG_ANY,"nssov: group entry %s contains invalid group name: \"%s\"\n",
entry->e_name.bv_val,names[i].bv_val,0);
}
else
......@@ -237,7 +241,7 @@ static int write_group(nssov_group_cbp *cbp,Entry *entry)
gid_t gid;
gid = strtol(gids[j].bv_val, &tmp, 0);
if ( *tmp ) {
Debug(LDAP_DEBUG_ANY,"nssov: group entry %s contains non-numeric %s value: \"%s\"",
Debug(LDAP_DEBUG_ANY,"nssov: group entry %s contains non-numeric %s value: \"%s\"\n",
entry->e_name.bv_val, cbp->mi->mi_attrs[GID_KEY].an_desc->ad_cname.bv_val,
names[i].bv_val);
continue;
......@@ -275,14 +279,14 @@ NSSOV_HANDLE(
cbp.name.bv_len = tmpint32;
cbp.name.bv_val = cbp.buf;
if (!isvalidgroupname(&cbp.name)) {
Debug(LDAP_DEBUG_ANY,"nssov_group_byname(%s): invalid group name",cbp.name.bv_val,0,0);
Debug(LDAP_DEBUG_ANY,"nssov_group_byname(%s): invalid group name\n",cbp.name.bv_val,0,0);
return -1;
}
cbp.wantmembers = 1;
cbp.ni = ni;
BER_BVZERO(&cbp.gidnum);
BER_BVZERO(&cbp.user);,
Debug(LDAP_DEBUG_TRACE,"nslcd_group_byname(%s)",cbp.name.bv_val,0,0);,
Debug(LDAP_DEBUG_TRACE,"nslcd_group_byname(%s)\n",cbp.name.bv_val,0,0);,
NSLCD_ACTION_GROUP_BYNAME,
nssov_filter_byname(cbp.mi,CN_KEY,&cbp.name,&filter)
)
......@@ -300,7 +304,7 @@ NSSOV_HANDLE(
cbp.ni = ni;
BER_BVZERO(&cbp.name);
BER_BVZERO(&cbp.user);,
Debug(LDAP_DEBUG_TRACE,"nssov_group_bygid(%s)",cbp.gidnum.bv_val,0,0);,
Debug(LDAP_DEBUG_TRACE,"nssov_group_bygid(%s)\n",cbp.gidnum.bv_val,0,0);,
NSLCD_ACTION_GROUP_BYGID,
nssov_filter_byid(cbp.mi,GID_KEY,&cbp.gidnum,&filter)
)
......@@ -314,14 +318,14 @@ NSSOV_HANDLE(
cbp.user.bv_len = tmpint32;
cbp.user.bv_val = cbp.buf;
if (!isvalidusername(&cbp.user)) {
Debug(LDAP_DEBUG_ANY,"nssov_group_bymember(%s): invalid user name",cbp.user.bv_val,0,0);
Debug(LDAP_DEBUG_ANY,"nssov_group_bymember(%s): invalid user name\n",cbp.user.bv_val,0,0);
return -1;
}
cbp.wantmembers = 0;
cbp.ni = ni;
BER_BVZERO(&cbp.name);
BER_BVZERO(&cbp.gidnum);,
Debug(LDAP_DEBUG_TRACE,"nssov_group_bymember(%s)",cbp.user.bv_val,0,0);,
Debug(LDAP_DEBUG_TRACE,"nssov_group_bymember(%s)\n",cbp.user.bv_val,0,0);,
NSLCD_ACTION_GROUP_BYMEMBER,
mkfilter_group_bymember(&cbp,&filter)
)
......@@ -334,7 +338,7 @@ NSSOV_HANDLE(
cbp.ni = ni;
BER_BVZERO(&cbp.name);
BER_BVZERO(&cbp.gidnum);,
Debug(LDAP_DEBUG_TRACE,"nssov_group_all()",0,0,0);,
Debug(LDAP_DEBUG_TRACE,"nssov_group_all()\n",0,0,0);,
NSLCD_ACTION_GROUP_ALL,
(filter=cbp.mi->mi_filter,0)
)
......@@ -59,7 +59,7 @@ static int write_host(nssov_host_cbp *cbp,Entry *entry)
a = attr_find( entry->e_attrs, cbp->mi->mi_attrs[0].an_desc );
if ( !a || !a->a_vals )
{
Debug(LDAP_DEBUG_ANY,"host entry %s does not contain %s value",
Debug(LDAP_DEBUG_ANY,"host entry %s does not contain %s value\n",
entry->e_name.bv_val, cbp->mi->mi_attrs[0].an_desc->ad_cname.bv_val, 0 );
return 0;
}
......@@ -82,7 +82,7 @@ static int write_host(nssov_host_cbp *cbp,Entry *entry)
a = attr_find( entry->e_attrs, cbp->mi->mi_attrs[1].an_desc );
if ( !a || !a->a_vals )
{
Debug(LDAP_DEBUG_ANY,"host entry %s does not contain %s value",
Debug(LDAP_DEBUG_ANY,"host entry %s does not contain %s value\n",
entry->e_name.bv_val, cbp->mi->mi_attrs[1].an_desc->ad_cname.bv_val, 0 );
return 0;
}
......@@ -119,7 +119,7 @@ NSSOV_HANDLE(
READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));
cbp.name.bv_len = tmpint32;
cbp.name.bv_val = cbp.buf;,
Debug(LDAP_DEBUG_TRACE,"nssov_host_byname(%s)",cbp.name.bv_val,0,0);,
Debug(LDAP_DEBUG_TRACE,"nssov_host_byname(%s)\n",cbp.name.bv_val,0,0);,
NSLCD_ACTION_HOST_BYNAME,
nssov_filter_byname(cbp.mi,0,&cbp.name,&filter)
)
......@@ -137,12 +137,12 @@ NSSOV_HANDLE(
/* translate the address to a string */
if (inet_ntop(af,addr,cbp.buf,sizeof(cbp.buf))==NULL)
{
Debug(LDAP_DEBUG_ANY,"nssov: unable to convert address to string",0,0,0);
Debug(LDAP_DEBUG_ANY,"nssov: unable to convert address to string\n",0,0,0);
return -1;
}
cbp.addr.bv_val = cbp.buf;
cbp.addr.bv_len = strlen(cbp.buf);,
Debug(LDAP_DEBUG_TRACE,"nssov_host_byaddr(%s)",cbp.addr.bv_val,0,0);,
Debug(LDAP_DEBUG_TRACE,"nssov_host_byaddr(%s)\n",cbp.addr.bv_val,0,0);,
NSLCD_ACTION_HOST_BYADDR,
nssov_filter_byid(cbp.mi,1,&cbp.addr,&filter)
)
......@@ -153,7 +153,7 @@ NSSOV_HANDLE(
/* no parameters to read */
BER_BVZERO(&cbp.name);
BER_BVZERO(&cbp.addr);,
Debug(LDAP_DEBUG_TRACE,"nssov_host_all()",0,0,0);,
Debug(LDAP_DEBUG_TRACE,"nssov_host_all()\n",0,0,0);,
NSLCD_ACTION_HOST_ALL,
(filter=cbp.mi->mi_filter,0)
)
# $OpenLDAP$
# $Id: ldapns.schema,v 1.3 2003/05/29 12:57:29 lukeh Exp $
# LDAP Name Service Additional Schema
# http://www.iana.org/assignments/gssapi-service-names
#
# Not part of the distribution: this is a workaround!
#
attributetype ( 1.3.6.1.4.1.5322.17.2.1 NAME 'authorizedService'
DESC 'IANA GSS-API authorized service name'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
objectclass ( 1.3.6.1.4.1.5322.17.1.1 NAME 'authorizedServiceObject'
DESC 'Auxiliary object class for adding authorizedService attribute'
SUP top
AUXILIARY
MAY authorizedService )
objectclass ( 1.3.6.1.4.1.5322.17.1.2 NAME 'hostObject'
DESC 'Auxiliary object class for adding host attribute'
SUP top
AUXILIARY
MAY host )
......@@ -91,7 +91,7 @@ static int write_netgroup_triple(TFILE *fp,const char *triple)
/* we should have a bracket now */
if (triple[i]!='(')
{
Debug(LDAP_DEBUG_ANY,"write_netgroup_triple(): entry does not begin with '(' (entry skipped)",0,0,0);
Debug(LDAP_DEBUG_ANY,"write_netgroup_triple(): entry does not begin with '(' (entry skipped)\n",0,0,0);
return 0;
}
i++;
......@@ -101,7 +101,7 @@ static int write_netgroup_triple(TFILE *fp,const char *triple)
/* nothing else to do */ ;
if (triple[i]!=',')
{
Debug(LDAP_DEBUG_ANY,"write_netgroup_triple(): missing ',' (entry skipped)",0,0,0);
Debug(LDAP_DEBUG_ANY,"write_netgroup_triple(): missing ',' (entry skipped)\n",0,0,0);
return 0;
}
hoste=i;
......@@ -112,7 +112,7 @@ static int write_netgroup_triple(TFILE *fp,const char *triple)
/* nothing else to do */ ;
if (triple[i]!=',')
{
Debug(LDAP_DEBUG_ANY,"write_netgroup_triple(): missing ',' (entry skipped)",0,0,0);
Debug(LDAP_DEBUG_ANY,"write_netgroup_triple(): missing ',' (entry skipped)\n",0,0,0);
return 0;
}
usere=i;
......@@ -123,7 +123,7 @@ static int write_netgroup_triple(TFILE *fp,const char *triple)
/* nothing else to do */ ;
if (triple[i]!=')')
{
Debug(LDAP_DEBUG_ANY,"write_netgroup_triple(): missing ')' (entry skipped)",0,0,0);
Debug(LDAP_DEBUG_ANY,"write_netgroup_triple(): missing ')' (entry skipped)\n",0,0,0);
return 0;
}
domaine=i;
......@@ -134,7 +134,7 @@ static int write_netgroup_triple(TFILE *fp,const char *triple)
/* if anything is left in the string we have a problem */
if (triple[i]!='\0')
{
Debug(LDAP_DEBUG_ANY,"write_netgroup_triple(): string contains trailing data (entry skipped)",0,0,0);
Debug(LDAP_DEBUG_ANY,"write_netgroup_triple(): string contains trailing data (entry skipped)\n",0,0,0);
return 0;
}
/* write strings */
......@@ -191,7 +191,7 @@ NSSOV_HANDLE(
READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));,
cbp.name.bv_len = tmpint32;
cbp.name.bv_val = cbp.buf;
Debug(LDAP_DEBUG_TRACE,"nssov_netgroup_byname(%s)",cbp.name.bv_val,0,0);,
Debug(LDAP_DEBUG_TRACE,"nssov_netgroup_byname(%s)\n",cbp.name.bv_val,0,0);,
NSLCD_ACTION_NETGROUP_BYNAME,
nssov_filter_byname(cbp.mi,0,&cbp.name,&filter)
)
......@@ -59,7 +59,7 @@ static int write_network(nssov_network_cbp *cbp,Entry *entry)
a = attr_find( entry->e_attrs, cbp->mi->mi_attrs[0].an_desc );
if ( !a || !a->a_vals )
{
Debug(LDAP_DEBUG_ANY,"network entry %s does not contain %s value",
Debug(LDAP_DEBUG_ANY,"network entry %s does not contain %s value\n",
entry->e_name.bv_val,cbp->mi->mi_attrs[0].an_desc->ad_cname.bv_val,0);
return 0;
}
......@@ -82,7 +82,7 @@ static int write_network(nssov_network_cbp *cbp,Entry *entry)
a = attr_find( entry->e_attrs, cbp->mi->mi_attrs[1].an_desc );
if ( !a || !a->a_vals )
{
Debug(LDAP_DEBUG_ANY,"network entry %s does not contain %s value",
Debug(LDAP_DEBUG_ANY,"network entry %s does not contain %s value\n",
entry->e_name.bv_val, cbp->mi->mi_attrs[1].an_desc->ad_cname.bv_val, 0 );
return 0;
}
......@@ -119,7 +119,7 @@ NSSOV_HANDLE(
READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));
cbp.name.bv_len = tmpint32;
cbp.name.bv_val = cbp.buf;,
Debug(LDAP_DEBUG_TRACE,"nssov_network_byname(%s)",cbp.name.bv_val,0,0);,
Debug(LDAP_DEBUG_TRACE,"nssov_network_byname(%s)\n",cbp.name.bv_val,0,0);,
NSLCD_ACTION_NETWORK_BYNAME,
nssov_filter_byname(cbp.mi,0,&cbp.name,&filter)
)
......@@ -137,12 +137,12 @@ NSSOV_HANDLE(
/* translate the address to a string */
if (inet_ntop(af,addr,cbp.buf,sizeof(cbp.buf))==NULL)
{
Debug(LDAP_DEBUG_ANY,"nssov: unable to convert address to string",0,0,0);
Debug(LDAP_DEBUG_ANY,"nssov: unable to convert address to string\n",0,0,0);
return -1;
}
cbp.addr.bv_val = cbp.buf;
cbp.addr.bv_len = strlen(cbp.buf);,
Debug(LDAP_DEBUG_TRACE,"nslcd_network_byaddr(%s)",cbp.addr.bv_val,0,0);,
Debug(LDAP_DEBUG_TRACE,"nslcd_network_byaddr(%s)\n",cbp.addr.bv_val,0,0);,
NSLCD_ACTION_NETWORK_BYADDR,
nssov_filter_byid(cbp.mi,1,&cbp.addr,&filter)
)
......@@ -153,7 +153,7 @@ NSSOV_HANDLE(
/* no parameters to read */
BER_BVZERO(&cbp.name);
BER_BVZERO(&cbp.addr);,
Debug(LDAP_DEBUG_TRACE,"nssov_network_all()",0,0,0);,
Debug(LDAP_DEBUG_TRACE,"nssov_network_all()\n",0,0,0);,
NSLCD_ACTION_NETWORK_ALL,
(filter=cbp.mi->mi_filter,0)
)
......@@ -197,8 +197,29 @@
#define NSLCD_ACTION_SHADOW_BYNAME 2001
#define NSLCD_ACTION_SHADOW_ALL 2005
#define NSLCD_ACTION_PAM_AUTHC 20001
#define NSLCD_ACTION_PAM_AUTHZ 20002
#define NSLCD_ACTION_PAM_SESS_O 20003
#define NSLCD_ACTION_PAM_SESS_C 20004
#define NSLCD_ACTION_PAM_PWMOD 20005
/* Request result codes. */
#define NSLCD_RESULT_END 3 /* key was not found */
#define NSLCD_RESULT_SUCCESS 0 /* everything ok */
/* Partial list of PAM result codes. */
#define NSLCD_PAM_SUCCESS 0 /* everything ok */
#define NSLCD_PAM_PERM_DENIED 6 /* Permission denied */
#define NSLCD_PAM_AUTH_ERR 7 /* Authc failure */
#define NSLCD_PAM_CRED_INSUFFICIENT 8 /* Cannot access authc data */
#define NSLCD_PAM_AUTHINFO_UNAVAIL 9 /* Cannot retrieve authc info */
#define NSLCD_PAM_USER_UNKNOWN 10 /* User not known */
#define NSLCD_PAM_MAXTRIES 11 /* Retry limit reached */
#define NSLCD_PAM_NEW_AUTHTOK_REQD 12 /* Password expired */
#define NSLCD_PAM_ACCT_EXPIRED 13 /* Account expired */
#define NSLCD_PAM_SESSION_ERR 14 /* Cannot make/remove session record */
#define NSLCD_PAM_AUTHTOK_DISABLE_AGING 23 /* Password aging disabled */
#define NSLCD_PAM_IGNORE 25 /* Ignore module */
#define NSLCD_PAM_ABORT 26 /* Fatal error */
#endif /* not _NSLCD_H */
......@@ -33,10 +33,10 @@ nss_ldap_so_SOURCES = common.c common.h prototypes.h \
../compat/attrs.h \
aliases.c ethers.c group.c hosts.c netgroup.c \
networks.c passwd.c protocols.c rpc.c services.c \
shadow.c
shadow.c pam.c
nss_ldap_so_LDFLAGS = -shared -Wl,-soname,$(NSS_LDAP_NSS_VERSIONED) \
-Wl,--version-script,\$(srcdir)/exports.linux
nss_ldap_so_LDADD = @nss_ldap_so_LIBS@ ../common/libtio.a
nss_ldap_so_LDADD = @nss_ldap_so_LIBS@ ../common/libtio.a -lpam
EXTRA_DIST = exports.linux
......
......@@ -70,7 +70,7 @@ am_nss_ldap_so_OBJECTS = common.$(OBJEXT) aliases.$(OBJEXT) \
ethers.$(OBJEXT) group.$(OBJEXT) hosts.$(OBJEXT) \
netgroup.$(OBJEXT) networks.$(OBJEXT) passwd.$(OBJEXT) \
protocols.$(OBJEXT) rpc.$(OBJEXT) services.$(OBJEXT) \
shadow.$(OBJEXT)
shadow.$(OBJEXT) pam.$(OBJEXT)
nss_ldap_so_OBJECTS = $(am_nss_ldap_so_OBJECTS)
nss_ldap_so_DEPENDENCIES = ../common/libtio.a
nss_ldap_so_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
......@@ -206,12 +206,12 @@ nss_ldap_so_SOURCES = common.c common.h prototypes.h \
../compat/attrs.h \
aliases.c ethers.c group.c hosts.c netgroup.c \
networks.c passwd.c protocols.c rpc.c services.c \
shadow.c
shadow.c pam.c
nss_ldap_so_LDFLAGS = -shared -Wl,-soname,$(NSS_LDAP_NSS_VERSIONED) \
-Wl,--version-script,\$(srcdir)/exports.linux
nss_ldap_so_LDADD = @nss_ldap_so_LIBS@ ../common/libtio.a
nss_ldap_so_LDADD = @nss_ldap_so_LIBS@ ../common/libtio.a -lpam
EXTRA_DIST = exports.linux
all: all-am
......@@ -266,6 +266,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hosts.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netgroup.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/networks.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/passwd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocols.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc.Po@am__quote@
......
......@@ -78,6 +78,14 @@ EXPORTED {
_nss_ldap_getspent_r;
_nss_ldap_endspent;
# pam - pluggable auth
pam_sm_acct_mgmt;
pam_sm_authenticate;
pam_sm_chauthtok;
pam_sm_close_session;
pam_sm_open_session;
pam_sm_setcred;
# everything else should not be exported
local:
*;
......
/*
pam.c - pam module functions
Copyright (C) 2009 Howard Chu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <syslog.h>
#include "prototypes.h"
#include "common.h"
#include "compat/attrs.h"
#ifndef HAVE_PAM_PAM_MODULES_H
#include <security/pam_modules.h>
#else
#include <pam/pam_modules.h>
#endif
#define CONST_ARG const
#define IGNORE_UNKNOWN 1
#define IGNORE_UNAVAIL 2
#define PLD_CTX "PAM_LDAPD_CTX"
#define NSS2PAM_RC(rc,ignore,ok) \
switch(rc) { \
case NSS_STATUS_SUCCESS: \
rc = ok; break; \
case NSS_STATUS_UNAVAIL: \
rc = (ignore & IGNORE_UNAVAIL) ? PAM_IGNORE : PAM_AUTHINFO_UNAVAIL; \
break; \
case NSS_STATUS_NOTFOUND: \
rc = (ignore & IGNORE_UNKNOWN) ? PAM_IGNORE: PAM_USER_UNKNOWN; \
break; \
default: \
rc = PAM_SYSTEM_ERR; break; \
}
typedef struct pld_ctx {
char *user;
char *dn;
char *tmpluser;
char *authzmsg;
char *oldpw;
int authok;
int authz;
int sessid;
char buf[1024];
} pld_ctx;
static int nslcd2pam_rc(int rc)