Browse Source

Добавлено ожидание домена через библиотеку ldap.

master
Mike khiretskiy 9 years ago
parent
commit
e4c3ef8cf3
  1. 2
      Makefile
  2. 226
      pam_client.c

2
Makefile

@ -8,7 +8,7 @@ SHARE := -g $(PIC)
pam_client: pam_client.c
$(CC) $(CFLAGS) $(SHARE) -c pam_client.c -o pam_client.o
$(LD_D) -o pam_client.so pam_client.o -lc -lpam
$(LD_D) -o pam_client.so pam_client.o -lc -lpam -lldap
clean: pam_client.so pam_client.o
$(RM) pam_client.o

226
pam_client.c

@ -22,14 +22,222 @@
#include <unistd.h>
#include <sys/types.h>
#include <ctype.h>
#include <syslog.h>
#include <ldap.h>
#include <asm/unistd.h>
#define PAM_LDAP_PATH_CONF "/etc/ldap.conf"
#define PAM_SM_AUTH
#define MAX_V 30
#define WAITTIME 30
typedef struct pam_config
{
/* file name read from */
char *configFile;
/* space delimited list of servers */
char *host;
/* port, expected to be common to all servers */
int port;
int version;
/* bind dn/pw for "anonymous" authentication */
char *binddn;
char *bindpw;
} pam_config_t;
static int
_alloc_config (pam_config_t ** presult)
{
pam_config_t *result;
if (*presult == NULL)
{
*presult = (pam_config_t *) calloc (1, sizeof (*result));
if (*presult == NULL)
return PAM_BUF_ERR;
}
result = *presult;
result->configFile = NULL;
result->host = NULL;
result->port = 0;
result->binddn = NULL;
result->bindpw = NULL;
result->version = LDAP_VERSION3;
return PAM_SUCCESS;
}
static int
_read_config (const char *configFile, pam_config_t ** presult)
{
/* this is the same configuration file as nss_ldap */
FILE *fp;
char b[BUFSIZ];
pam_config_t *result;
if (_alloc_config (presult) != PAM_SUCCESS)
{
return PAM_BUF_ERR;
}
result = *presult;
/* configuration file location is configurable; default /etc/ldap.conf */
if (configFile == NULL)
{
configFile = PAM_LDAP_PATH_CONF;
result->configFile = NULL;
}
else
{
result->configFile = strdup (configFile);
if (result->configFile == NULL)
return PAM_BUF_ERR;
}
fp = fopen (configFile, "r");
if (fp == NULL)
{
return PAM_SERVICE_ERR;
}
while (fgets (b, sizeof (b), fp) != NULL)
{
char *k, *v;
int len;
if (*b == '\n' || *b == '#')
continue;
k = b;
v = k;
while (*v != '\0' && *v != ' ' && *v != '\t')
v++;
if (*v == '\0')
continue;
*(v++) = '\0';
/* skip all whitespaces between keyword and value */
while (*v == ' ' || *v == '\t')
v++;
/* kick off all whitespaces and newline at the end of value */
len = strlen (v) - 1;
while (v[len] == ' ' || v[len] == '\t' || v[len] == '\n')
--len;
v[len + 1] = '\0';
if (!strcasecmp (k, "host"))
{
result->host = strdup (v);
}
else if (!strcasecmp (k, "binddn"))
{
result->binddn = strdup (v);
}
else if (!strcasecmp (k, "bindpw"))
{
result->bindpw = strdup (v);
}
else if (!strcasecmp (k, "port"))
{
result->port = atoi (v);
}
else if (!strcasecmp (k, "ldap_version"))
{
result->version = atoi (v);
}
}
if (result->host == NULL || result->binddn == NULL ||
result->bindpw == NULL)
{
/*
* According to PAM Documentation, such an error in a config file
* SHOULD be logged at LOG_ALERT level
*/
syslog (LOG_ALERT, "pam_ldap: missing \"host\" in file \"%s\"",
configFile);
return PAM_SERVICE_ERR;
}
if (result->port == 0)
{
result->port = LDAP_PORT;
}
fclose (fp);
/* can't use _pam_overwrite because it only goes to end of string,
* not the buffer
*/
memset (b, 0, BUFSIZ);
return PAM_SUCCESS;
}
static void
_release_config (pam_config_t ** pconfig)
{
pam_config_t *c;
c = *pconfig;
if (c == NULL)
return;
if (c->configFile != NULL)
free (c->configFile);
if (c->host != NULL)
free (c->host);
if (c->binddn != NULL)
free (c->binddn);
if (c->bindpw != NULL)
free (c->bindpw);
}
static int
_check_ldap (int retry_count)
{
int result;
struct berval userpw;
struct berval *servcred;
char buf[BUFSIZ];
LDAP *ld;
pam_config_t * config= NULL;
if(_read_config(NULL,&config) != PAM_SUCCESS) {
if(config)
_release_config(&config);
return PAM_SERVICE_ERR;
}
snprintf(buf,BUFSIZ,"ldap://%s:%d",config->host,config->port);
if(ldap_initialize(&ld,buf) == LDAP_SUCCESS &&
ldap_set_option(ld,LDAP_OPT_PROTOCOL_VERSION,
&config->version) == LDAP_SUCCESS ) {
userpw.bv_val = config->bindpw;
userpw.bv_len = (userpw.bv_val != 0) ? strlen (userpw.bv_val) : 0;
for(;retry_count;retry_count--) {
if (ldap_sasl_bind_s(ld,config->binddn,LDAP_SASL_SIMPLE,
&userpw, NULL, NULL,&servcred) == LDAP_SUCCESS) {
result = PAM_SUCCESS;
break;
}
else {
result = PAM_TRY_AGAIN;
}
sleep(1);
}
}
_release_config(&config);
return result;
}
int file_exists(const char *fname) {
return access(fname, 0) != -1;
}
@ -47,13 +255,15 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags
// wait for client daemon
if (file_exists(boot_client) || file_exists(default_client)) {
for(i=0;i<WAITTIME;i++) {
if(file_exists(started_client) ||
file_exists(started_local)) {
break;
}
sleep(1);
}
for(i=0;i<WAITTIME;i++) {
if(file_exists(started_client) ||
file_exists(started_local)) {
if(_check_ldap(WAITTIME-i)==PAM_SUCCESS)
return PAM_SUCCESS;
break;
}
sleep(1);
}
}
// break auth if not exists ldap.conf
if (!file_exists(ldap_conf)) {

Loading…
Cancel
Save