Commit 57af0cea authored by Quanah Gibson-Mount's avatar Quanah Gibson-Mount
Browse files

nss overlay

parent f2d894e2
OpenLDAP 2.4 Change Log
OpenLDAP 2.4.11 Engineering
Added slapo-nssov contrib module
OpenLDAP 2.4.10 Release (2008/06/08)
Fixed libldap file descriptor leak with SELinux (ITS#5507)
......
......@@ -2,3 +2,4 @@ List of OpenLDAP Configuration OIDs allocated to contrib modules
OLcfgCt{Oc|At}:1 smbk5pwd
OLcfgCt{Oc|At}:2 autogroup
OLcfgCt{Oc|At}:3 nssov
# $OpenLDAP$
# Copyright 2008 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
# Public License.
#
# A copy of this license is available in the file LICENSE in the
# top-level directory of the distribution or, alternatively, at
# <http://www.OpenLDAP.org/license.html>.
# Path to the OpenLDAP source tree
LDAPSRC=../../..
# Path to the OpenLDAP object tree - same as above unless
# you're doing out-of-tree builds.
LDAPOBJ=../../..
LIBTOOL=$(LDAPOBJ)/libtool
OPT=-g -O2
CC=gcc
LDAP_INC=-I$(LDAPOBJ)/include -I$(LDAPSRC)/include -I$(LDAPSRC)/servers/slapd
NLDAPD_INC=-Inss-ldapd
INCS=$(LDAP_INC) $(NLDAPD_INC)
LDAP_LIB=-lldap_r -llber
LIBS=$(LDAP_LIB)
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
.SUFFIXES: .c .o .lo
.c.lo:
$(LIBTOOL) --mode=compile $(CC) $(OPT) $(DEFS) $(INCS) -c $?
tio.lo: nss-ldapd/common/tio.c
$(LIBTOOL) --mode=compile $(CC) $(OPT) $(DEFS) $(NLDAPD_INC) -c $?
$(OBJS): nssov.h
nssov.la: $(OBJS) $(XOBJS)
$(LIBTOOL) --mode=link $(CC) $(OPT) -version-info 0:0:0 \
-rpath /usr/local/libexec/openldap -module -o $@ $(OBJS) $(XOBJS) $(LIBS)
Copyright 2008 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
Public License.
A copy of this license is available in the file LICENSE in the
top-level directory of the distribution or, alternatively, at
<http://www.OpenLDAP.org/license.html>.
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.
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
nslcd daemon; this overlay replaces that part. You should already
be familiar with the RFC2307 and RFC2307bis schema to use this
overlay. See the nss-ldapd/README for more information on the
schema and which features are supported.
To use the overlay, add:
include <path to>nis.schema
moduleload <path to>nssov.so
...
database hdb
...
overlay nssov
to your slapd configuration file. (The nis.schema file contains
the original RFC2307 schema. Some modifications will be needed to
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>
where the <service> may be one of
alias
ether
group
host
netgroup
network
passwd
protocol
rpc
service
shadow
and the <url> must be of the form
ldap:///[<basedn>][??[<scope>][?<filter>]]
The <basedn> will default to the first suffix of the current database.
The <scope> defaults to "subtree". The default <filter> depends on which
service is being used.
If the local database is actually a proxy to a foreign LDAP server, some
mapping of schema may be needed. Some simple attribute substitutions may
be performed using
nssov-map <service> <orig> <new>
See the nss-ldapd/README for the original attribute names used in this code.
The overlay also supports dynamic configuration in cn=config. The layout
of the config entry is
dn: olcOverlay={0}nssov,ocDatabase={1}hdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcNssOvConfig
olcOverlay: {0}nssov
olcNssSvc: 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.
/* alias.c - mail alias lookup routines */
/* $OpenLDAP$ */
/*
* Copyright 2008 by 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
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/*
* This code references portions of the nss-ldapd package
* written by Arthur de Jong. The nss-ldapd code was forked
* from the nss-ldap library written by Luke Howard.
*/
#include "nssov.h"
/* Vendor-specific attributes and object classes.
* (Mainly from Sun.)
* ( 1.3.6.1.4.1.42.2.27.1.2.5 NAME 'nisMailAlias' SUP top STRUCTURAL
* DESC 'NIS mail alias'
* MUST cn
* MAY rfc822MailMember )
*/
/* the basic search filter for searches */
static struct berval alias_filter = BER_BVC("(objectClass=nisMailAlias)");
/* the attributes to request with searches */
static struct berval alias_keys[] = {
BER_BVC("cn"),
BER_BVC("rfc822MailMember"),
BER_BVNULL
};
NSSOV_INIT(alias)
NSSOV_CBPRIV(alias,
struct berval name;
char buf[256];);
static int write_alias(nssov_alias_cbp *cbp,Entry *entry)
{
int32_t tmpint32,tmp2int32,tmp3int32;
struct berval tmparr[2], empty;
struct berval *names, *members;
Attribute *a;
int i;
/* get the name of the alias */
if (BER_BVISNULL(&cbp->name))
{
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",
entry->e_name.bv_val,cbp->mi->mi_attrs[0].an_desc->ad_cname.bv_val,0 );
return 0;
}
names = a->a_vals;
}
else
{
names=tmparr;
names[0]=cbp->name;
BER_BVZERO(&names[1]);
}
/* get the members of the alias */
a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[1].an_desc);
if ( !a ) {
BER_BVZERO( &empty );
members = &empty;
} else {
members = a->a_vals;
}
/* for each name, write an entry */
for (i=0;!BER_BVISNULL(&names[i]);i++)
{
WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
WRITE_BERVAL(cbp->fp,&names[i]);
WRITE_BVARRAY(cbp->fp,members);
}
return 0;
}
NSSOV_CB(alias)
NSSOV_HANDLE(
alias,byname,
char fbuf[1024];
struct berval filter = {sizeof(fbuf)};
filter.bv_val = fbuf;
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);,
NSLCD_ACTION_ALIAS_BYNAME,
nssov_filter_byname(cbp.mi,0,&cbp.name,&filter)
)
NSSOV_HANDLE(
alias,all,
struct berval filter;
/* no parameters to read */
BER_BVZERO(&cbp.name);,
Debug(LDAP_DEBUG,"nssov_alias_all()",0,0,0);,
NSLCD_ACTION_ALIAS_ALL,
(filter=cbp.mi->mi_filter,0)
)
/* ether.c - ethernet address lookup routines */
/* $OpenLDAP$ */
/*
* Copyright 2008 by 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
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/*
* This code references portions of the nss-ldapd package
* written by Arthur de Jong. The nss-ldapd code was forked
* from the nss-ldap library written by Luke Howard.
*/
#include "nssov.h"
struct ether_addr {
uint8_t ether_addr_octet[6];
};
/* ( nisSchema.2.11 NAME 'ieee802Device' SUP top AUXILIARY
* DESC 'A device with a MAC address; device SHOULD be
* used as a structural class'
* MAY macAddress )
*/
/* the basic search filter for searches */
static struct berval ether_filter = BER_BVC("(objectClass=ieee802Device)");
/* the attributes to request with searches */
static struct berval ether_keys[] = {
BER_BVC("cn"),
BER_BVC("macAddress"),
BER_BVNULL
};
NSSOV_INIT(ether)
NSSOV_CBPRIV(ether,
char buf[256];
struct berval name;
struct berval addr;);
#define WRITE_ETHER(fp,addr) \
{int ao[6]; \
sscanf(addr.bv_val,"%02x:%02x:%02x:%02x:%02x:%02x", \
&ao[0], &ao[1], &ao[2], &ao[3], &ao[4], &ao[5] );\
tmpaddr.ether_addr_octet[0] = ao[0]; \
tmpaddr.ether_addr_octet[1] = ao[1]; \
tmpaddr.ether_addr_octet[2] = ao[2]; \
tmpaddr.ether_addr_octet[3] = ao[3]; \
tmpaddr.ether_addr_octet[4] = ao[4]; \
tmpaddr.ether_addr_octet[5] = ao[5]; } \
WRITE_TYPE(fp,tmpaddr,uint8_t[6]);
static int write_ether(nssov_ether_cbp *cbp,Entry *entry)
{
int32_t tmpint32;
struct ether_addr tmpaddr;
struct berval tmparr[2], empty;
struct berval *names,*ethers;
Attribute *a;
int i,j;
/* get the name of the ether entry */
if (BER_BVISNULL(&cbp->name))
{
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",
entry->e_name.bv_val,cbp->mi->mi_attrs[0].an_desc->ad_cname.bv_val,0 );
return 0;
}
names = a->a_vals;
}
else
{
names=tmparr;
names[0]=cbp->name;
BER_BVZERO(&names[1]);
}
/* get the addresses */
if (BER_BVISNULL(&cbp->addr))
{
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",
entry->e_name.bv_val,cbp->mi->mi_attrs[1].an_desc->ad_cname.bv_val,0 );
return 0;
}
ethers = a->a_vals;
/* TODO: move parsing of addresses up here */
}
else
{
ethers=tmparr;
ethers[0]=cbp->addr;
BER_BVZERO(&ethers[1]);
}
/* write entries for all names and addresses */
for (i=0;!BER_BVISNULL(&names[i]);i++)
for (j=0;!BER_BVISNULL(&ethers[j]);j++)
{
WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
WRITE_BERVAL(cbp->fp,&names[i]);
WRITE_ETHER(cbp->fp,ethers[j]);
}
return 0;
}
NSSOV_CB(ether)
NSSOV_HANDLE(
ether,byname,
char fbuf[1024];
struct berval filter = {sizeof(fbuf)};
filter.bv_val = fbuf;
BER_BVZERO(&cbp.addr);
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);,
NSLCD_ACTION_ETHER_BYNAME,
nssov_filter_byname(cbp.mi,0,&cbp.name,&filter)
)
NSSOV_HANDLE(
ether,byether,
struct ether_addr addr;
char fbuf[1024];
struct berval filter = {sizeof(fbuf)};
filter.bv_val = fbuf;
BER_BVZERO(&cbp.name);
READ_TYPE(fp,addr,uint8_t[6]);
cbp.addr.bv_len = snprintf(cbp.buf,sizeof(cbp.buf), "%x:%x:%x:%x:%x:%x",
addr.ether_addr_octet[0],
addr.ether_addr_octet[1],
addr.ether_addr_octet[2],
addr.ether_addr_octet[3],
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);,
NSLCD_ACTION_ETHER_BYETHER,
nssov_filter_byid(cbp.mi,1,&cbp.addr,&filter)
)
NSSOV_HANDLE(
ether,all,
struct berval filter;
/* no parameters to read */
BER_BVZERO(&cbp.name);
BER_BVZERO(&cbp.addr);,
Debug(LDAP_DEBUG_TRACE,"nssov_ether_all()",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.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/*
* This code references portions of the nss-ldapd package
* written by Arthur de Jong. The nss-ldapd code was forked
* from the nss-ldap library written by Luke Howard.
*/
#include "nssov.h"
/* for gid_t */
#include <grp.h>
/* ( nisSchema.2.2 NAME 'posixGroup' SUP top STRUCTURAL
* DESC 'Abstraction of a group of accounts'
* MUST ( cn $ gidNumber )
* MAY ( userPassword $ memberUid $ description ) )
*
* apart from that the above the uniqueMember attributes may be
* supported in a coming release (they map to DNs, which is an extra
* lookup step)
*
* using nested groups (groups that are member of a group) is currently
* not supported, this may be added in a later release
*/
/* the basic search filter for searches */
static struct berval group_filter = BER_BVC("(objectClass=posixGroup)");
/* the attributes to request with searches */
static struct berval group_keys[] = {
BER_BVC("cn"),
BER_BVC("userPassword"),
BER_BVC("gidNumber"),
BER_BVC("memberUid"),
BER_BVC("uniqueMember"),
BER_BVNULL
};
#define CN_KEY 0
#define PWD_KEY 1
#define GID_KEY 2
#define UID_KEY 3
#define MEM_KEY 4
/* default values for attributes */
static struct berval default_group_userPassword = BER_BVC("*"); /* unmatchable */
NSSOV_CBPRIV(group,
nssov_info *ni;
char buf[256];
struct berval name;
struct berval gidnum;
struct berval user;
int wantmembers;);
/* create a search filter for searching a group entry
by member uid, return -1 on errors */
static int mkfilter_group_bymember(nssov_group_cbp *cbp,struct berval *buf)
{
struct berval dn;
/* try to translate uid to DN */
nssov_uid2dn(cbp->op,cbp->ni,&cbp->user,&dn);
if (BER_BVISNULL(&dn)) {
if (cbp->user.bv_len + cbp->mi->mi_filter.bv_len + cbp->mi->mi_attrs[UID_KEY].an_desc->ad_cname.bv_len + 6 >
buf->bv_len )
return -1;
buf->bv_len = snprintf(buf->bv_val, buf->bv_len, "(&%s(%s=%s))",
cbp->mi->mi_filter.bv_val, cbp->mi->mi_attrs[UID_KEY].an_desc->ad_cname.bv_val,
cbp->user.bv_val );
} else { /* also lookup using user DN */
if (cbp->user.bv_len + cbp->mi->mi_filter.bv_len + cbp->mi->mi_attrs[UID_KEY].an_desc->ad_cname.bv_len +
dn.bv_len + cbp->mi->mi_attrs[MEM_KEY].an_desc->ad_cname.bv_len + 12 > buf->bv_len )
return -1;
buf->bv_len = snprintf(buf->bv_val, buf->bv_len, "(&%s(|(%s=%s)(%s=%s)))",
cbp->mi->mi_filter.bv_val,
cbp->mi->mi_attrs[UID_KEY].an_desc->ad_cname.bv_val, cbp->user.bv_val,
cbp->mi->mi_attrs[MEM_KEY].an_desc->ad_cname.bv_val, dn.bv_val );
}
return 0;
}
NSSOV_INIT(group)
/*
Checks to see if the specified name is a valid group name.
This test is based on the definition from POSIX (IEEE Std 1003.1, 2004,
3.189 Group Name and 3.276 Portable Filename Character Set):
http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_189
http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_276
The standard defines group names valid if they only contain characters from
the set [A-Za-z0-9._-] where the hyphen should not be used as first
character.
*/
static int isvalidgroupname(struct berval *name)
{
int i;
if ( !name->bv_val || !name->bv_len )
return 0;
/* check first character */
if ( ! ( (name->bv_val[0]>='A' && name->bv_val[0] <= 'Z') ||
(name->bv_val[0]>='a' && name->bv_val[0] <= 'z') ||
(name->bv_val[0]>='0' && name->bv_val[0] <= '9') ||
name->bv_val[0]=='.' || name->bv_val[0]=='_' ) )
return 0;
/* check other characters */
for (i=1;i<name->bv_len;i++)
{
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') ||
name->bv_val[i]=='.' || name->bv_val[i]=='_' || name->bv_val[i]=='-') )
return 0;
}
/* no test failed so it must be good */
return -1;
}
static int write_group(nssov_group_cbp *cbp,Entry *entry)
{
struct berval tmparr[2], tmpgid[2];
struct berval *names,*gids,*members;
struct berval passwd = {0};
Attribute *a;
int i,j,nummembers,rc;
/* get group name (cn) */
if (BER_BVISNULL(&cbp->name))
{
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",
entry->e_name.bv_val, cbp->mi->mi_attrs[CN_KEY].an_desc->ad_cname.bv_val,0);
return 0;
}
names = a->a_vals;
}
else
{
names=tmparr;
names[0]=cbp->name;
BER_BVZERO(&names[1]);
}
/* get the group id(s) */
if (BER_BVISNULL(&cbp->gidnum))
{
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",
entry->e_name.bv_val, cbp->mi->mi_attrs[GID_KEY].an_desc->ad_cname.bv_val,0);
return 0;
}
gids = a->a_vals;
}
else
{
gids=tmpgid;
gids[0]=cbp->gidnum;
BER_BVZERO(&gids[1]);
}
/* get group passwd (userPassword) (use only first entry) */
a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[PWD_KEY].an_desc);