*
* Copyright 2008-2013 The OpenLDAP Foundation.
* Portions Copyright 2008 by Howard Chu, Symas Corp.
+ * Portions Copyright 2013 by Ted C. Cheng, Symas Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
return 0;
}
+int nssov_config(nssov_info *ni,TFILE *fp,Operation *op)
+{
+ int opt;
+ int32_t tmpint32;
+ struct berval *msg = BER_BVC("");
+ int rc = NSLCD_PAM_SUCCESS;
+
+ READ_INT32(fp,opt);
+
+ Debug(LDAP_DEBUG_TRACE, "nssov_config (%d)\n",opt,0,0);
+
+ switch (opt) {
+ case NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE:
+ /* request for pam password_prothibit_message */
+ /* nssov_pam prohibits password */
+ if (!BER_BVISEMPTY(&ni->ni_pam_password_prohibit_message)) {
+ Debug(LDAP_DEBUG_TRACE,"nssov_config(): %s (%s)\n",
+ "password_prohibit_message",
+ ni->ni_pam_password_prohibit_message.bv_val,0);
+ msg = &ni->ni_pam_password_prohibit_message;
+ rc = NSLCD_PAM_PERM_DENIED;
+ }
+ /* fall through */
+ default:
+ break;
+ }
+
+done:;
+ WRITE_INT32(fp,NSLCD_VERSION);
+ WRITE_INT32(fp,NSLCD_ACTION_CONFIG_GET);
+ WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
+ WRITE_BERVAL(fp,msg);
+ WRITE_INT32(fp,NSLCD_RESULT_END);
+ return 0;
+}
+
+
/* read a request message, returns <0 in case of errors,
this function closes the socket */
static void handleconnection(nssov_info *ni,int sock,Operation *op)
{
TFILE *fp;
int32_t action;
- struct timeval readtimeout,writetimeout;
+ int readtimeout,writetimeout;
uid_t uid;
gid_t gid;
char authid[sizeof("gidNumber=4294967295+uidNumber=424967295,cn=peercred,cn=external,cn=auth")];
/* Should do authid mapping too */
op->o_dn.bv_len = sprintf(authid,"gidNumber=%d+uidNumber=%d,cn=peercred,cn=external,cn=auth",
- (int)uid, (int)gid );
+ (int)gid, (int)uid );
op->o_dn.bv_val = authid;
op->o_ndn = op->o_dn;
- /* set the timeouts */
- readtimeout.tv_sec=0; /* clients should send their request quickly */
- readtimeout.tv_usec=500000;
- writetimeout.tv_sec=5; /* clients could be taking some time to process the results */
- writetimeout.tv_usec=0;
+ /* set the timeouts:
+ * read timeout is half a second because clients should send their request
+ * quickly, write timeout is 60 seconds because clients could be taking some
+ * time to process the results
+ */
+ readtimeout = 500;
+ writetimeout = 60000;
/* create a stream object */
- if ((fp=tio_fdopen(sock,&readtimeout,&writetimeout,
+ if ((fp=tio_fdopen(sock,readtimeout,writetimeout,
READBUFFER_MINSIZE,READBUFFER_MAXSIZE,
WRITEBUFFER_MINSIZE,WRITEBUFFER_MAXSIZE))==NULL)
{
case NSLCD_ACTION_PAM_SESS_O: if (uid==0) (void)pam_sess_o(ni,fp,op); break;
case NSLCD_ACTION_PAM_SESS_C: if (uid==0) (void)pam_sess_c(ni,fp,op); break;
case NSLCD_ACTION_PAM_PWMOD: (void)pam_pwmod(ni,fp,op); break;
+ case NSLCD_ACTION_CONFIG_GET: (void)nssov_config(ni,fp,op); break;
default:
Debug( LDAP_DEBUG_ANY,"nssov: invalid request id: %d",(int)action,0,0);
break;
"DESC 'Services for which sessions will be recorded' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
+ { "nssov-pam-password-prohibit-message",
+ "password_prohibit_message", 2, 2, 0,
+ ARG_OFFSET|ARG_BERVAL,
+ (void *)offsetof(struct nssov_info, ni_pam_password_prohibit_message),
+ "(OLcfgCtAt:3.12 NAME 'olcNssPamPwdProhibitMsg' "
+ "DESC 'Prohibit password modification message' "
+ "EQUALITY caseIgnoreMatch "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+ { "nssov-pam-pwdmgr-dn",
+ "pwdmgr_dn", 2, 2, 0,
+ ARG_OFFSET|ARG_BERVAL,
+ (void *)offsetof(struct nssov_info, ni_pam_pwdmgr_dn),
+ "(OLcfgCtAt:3.13 NAME 'olcPamPwdmgrDn' "
+ "DESC 'Password Manager DN' "
+ "EQUALITY distinguishedNameMatch "
+ "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
+ { "nssov-pam-pwdmgr-pwd",
+ "pwdmgr_pwd", 2, 2, 0,
+ ARG_OFFSET|ARG_BERVAL,
+ (void *)offsetof(struct nssov_info, ni_pam_pwdmgr_pwd),
+ "(OLcfgCtAt:3.14 NAME 'olcPamPwdmgrPwd' "
+ "DESC 'Password Manager Pwd' "
+ "EQUALITY octetStringMatch "
+ "SYNTAX OMsOctetString SINGLE-VALUE )", NULL, NULL },
{ NULL, NULL, 0,0,0, ARG_IGNORED }
};
*
* Copyright 2008-2013 The OpenLDAP Foundation.
* Portions Copyright 2008 by Howard Chu, Symas Corp.
+ * Portions Copyright 2013 by Ted C. Cheng, Symas Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
struct berval pwd;
int authz;
struct berval msg;
+ int ispwdmgr;
};
static int pam_bindcb(
if (!isvalidusername(&pi->uid)) {
Debug(LDAP_DEBUG_ANY,"nssov_pam_uid2dn(%s): invalid user name\n",
- pi->uid.bv_val,0,0);
+ pi->uid.bv_val ? pi->uid.bv_val : "NULL",0,0);
return NSLCD_PAM_USER_UNKNOWN;
}
pi->msg.bv_val = pi->pwd.bv_val;
pi->msg.bv_len = 0;
pi->authz = NSLCD_PAM_SUCCESS;
- BER_BVZERO(&pi->dn);
- rc = pam_uid2dn(ni, op, pi);
- if (rc) goto finish;
+ if (!pi->ispwdmgr) {
- if (BER_BVISEMPTY(&pi->pwd)) {
- rc = NSLCD_PAM_IGNORE;
- goto finish;
- }
+ BER_BVZERO(&pi->dn);
+ rc = pam_uid2dn(ni, op, pi);
+ if (rc) goto finish;
- /* Should only need to do this once at open time, but there's always
- * the possibility that ppolicy will get loaded later.
- */
- if (!ppolicy_cid) {
- rc = slap_find_control_id(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
- &ppolicy_cid);
- }
- /* of course, 0 is a valid cid, but it won't be ppolicy... */
- if (ppolicy_cid) {
- op->o_ctrlflag[ppolicy_cid] = SLAP_CONTROL_NONCRITICAL;
+ if (BER_BVISEMPTY(&pi->pwd)) {
+ rc = NSLCD_PAM_PERM_DENIED;
+ goto finish;
+ }
+
+ /* Should only need to do this once at open time, but there's always
+ * the possibility that ppolicy will get loaded later.
+ */
+ if (!ppolicy_cid) {
+ rc = slap_find_control_id(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
+ &ppolicy_cid);
+ }
+ /* of course, 0 is a valid cid, but it won't be ppolicy... */
+ if (ppolicy_cid) {
+ op->o_ctrlflag[ppolicy_cid] = SLAP_CONTROL_NONCRITICAL;
+ }
}
+
cb.sc_response = pam_bindcb;
cb.sc_private = pi;
op->o_callback = &cb;
default: rc = NSLCD_PAM_AUTH_ERR; break;
}
finish:
+ Debug(LDAP_DEBUG_ANY,"pam_do_bind (%s): rc (%d)\n",
+ pi->dn.bv_val ? pi->dn.bv_val : "NULL", rc, 0);
return rc;
}
pi.pwd.bv_val = pwdc;
pi.pwd.bv_len = tmpint32;
- Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(%s)\n",pi.uid.bv_val,0,0);
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(%s)\n",
+ pi.uid.bv_val ? pi.uid.bv_val : "NULL",0,0);
+
+ pi.ispwdmgr = 0;
+
+ /* if service is "passwd" and "nssov-pam-password-prohibit-message */
+ /* is set, deny the auth request */
+ if (!strcmp(svcc, "passwd") &&
+ !BER_BVISEMPTY(&ni->ni_pam_password_prohibit_message)) {
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(): %s (%s)\n",
+ "password_prohibit_message for passwd",
+ ni->ni_pam_password_prohibit_message.bv_val,0);
+ ber_str2bv(ni->ni_pam_password_prohibit_message.bv_val, 0, 0, &pi.msg);
+ pi.authz = NSLCD_PAM_PERM_DENIED;
+ rc = NSLCD_PAM_PERM_DENIED;
+ goto finish;
+ }
+
+ /* if username is null, pwdmgr password preliminary check */
+ if (BER_BVISEMPTY(&pi.uid)) {
+ if (BER_BVISEMPTY(&ni->ni_pam_pwdmgr_dn)) {
+ /* pwdmgr dn not configured */
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(prelim check): %s\n",
+ "pwdmgr dn not configured", 0, 0);
+ ber_str2bv("pwdmgr dn not configured", 0, 0, &pi.msg);
+ pi.authz = NSLCD_PAM_PERM_DENIED;
+ rc = NSLCD_PAM_PERM_DENIED;
+ goto finish;
+ } else {
+ /* use pwdmgr dn */
+ ber_str2bv(ni->ni_pam_pwdmgr_dn.bv_val, 0, 0, &pi.dn);
+ }
+
+ /* use pwdmgr pwd if configured */
+ if (BER_BVISEMPTY(&pi.pwd)) {
+ if (BER_BVISEMPTY(&ni->ni_pam_pwdmgr_pwd)) {
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(prelim check): %s\n",
+ "no pwdmgr pwd", 0, 0);
+ ber_str2bv("pwdmgr pwd not configured", 0, 0, &pi.msg);
+ pi.authz = NSLCD_PAM_PERM_DENIED;
+ rc = NSLCD_PAM_PERM_DENIED;
+ goto finish;
+ }
+ /* use configured pwdmgr pwd */
+ memset((void *) pwdc, 0, 256);
+ strncpy(pi.pwd.bv_val, ni->ni_pam_pwdmgr_pwd.bv_val,
+ ni->ni_pam_pwdmgr_pwd.bv_len);
+ pi.pwd.bv_len = ni->ni_pam_pwdmgr_pwd.bv_len;
+ }
+ pi.ispwdmgr = 1;
+ }
+
rc = pam_do_bind(ni, fp, op, &pi);
finish:
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(%s): rc (%d)\n",
+ pi.dn.bv_val ? pi.dn.bv_val : "NULL",rc,0);
WRITE_INT32(fp,NSLCD_VERSION);
WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHC);
WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
tty.bv_val = ttyc;
tty.bv_len = tmpint32;
- Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(%s)\n",dn.bv_val,0,0);
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(%s)\n",
+ dn.bv_val ? dn.bv_val : "NULL",0,0);
/* If we didn't do authc, we don't have a DN yet */
if (BER_BVISEMPTY(&dn)) {
if (e) {
be_entry_release_r(op, e);
}
+ switch (rc) {
+ case NSLCD_PAM_SUCCESS:
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(): success\n", 0,0,0);
+ break;
+ case NSLCD_PAM_PERM_DENIED:
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(): %s\n",
+ authzmsg.bv_val ? authzmsg.bv_val : "NULL",0,0);
+ break;
+ default:
+ Debug(LDAP_DEBUG_TRACE,
+ "nssov_pam_authz(): permission denied, rc (%d)\n",
+ rc, 0, 0);
+ }
return 0;
}
struct berval timestamp, bv[2], *nbv;
time_t stamp;
Modifications mod;
+ int rc = 0;
+ int sessionID = -1;
READ_STRING(fp,uidc);
uid.bv_val = uidc;
Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(%s)\n",
action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', dn.bv_val,0);
- if (!dn.bv_len || !ni->ni_pam_sessions) return 0;
+ if (!dn.bv_len) {
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(): %s\n",
+ action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', "null DN",0);
+ rc = -1;
+ goto done;
+ }
+
+ if (!ni->ni_pam_sessions) {
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(): %s\n",
+ action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c',
+ "pam session(s) not configured, ignored",0);
+ rc = -1;
+ goto done;
+ }
{
int i, found=0;
break;
}
}
- if (!found) return 0;
+ if (!found) {
+ Debug(LDAP_DEBUG_TRACE,
+ "nssov_pam_sess_%c(): service(%s) not configured, ignored\n",
+ action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c',
+ svc.bv_val,0);
+ rc = -1;
+ goto done;
+ }
}
slap_op_time( &op->o_time, &op->o_tincr );
sprintf(bv[0].bv_val, "%s %s %s %s (%s@%s)",
timestamp.bv_val, global_host_bv.bv_val, svc.bv_val, tty.bv_val,
ruser.bv_val, rhost.bv_val);
+
+ Debug(LDAP_DEBUG_TRACE, "nssov_pam_sess_%c(): loginStatus (%s) \n",
+ action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', bv[0].bv_val,0);
mod.sml_numvals = 1;
mod.sml_values = bv;
op->orm_no_opattrs = 1;
op->o_req_dn = dn;
op->o_req_ndn = dn;
- op->o_bd->be_modify( op, &rs );
+ if (op->o_bd->be_modify( op, &rs ) != LDAP_SUCCESS) {
+ Debug(LDAP_DEBUG_TRACE,
+ "nssov_pam_sess_%c(): modify op failed\n",
+ action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c',
+ 0,0);
+ rc = -1;
+ }
+
if ( mod.sml_next ) {
slap_mods_free( mod.sml_next, 1 );
}
ber_bvarray_free_x( nbv, op->o_tmpmemctx );
+done:;
+
+ if (rc == 0) {
+ Debug(LDAP_DEBUG_TRACE,
+ "nssov_pam_sess_%c(): success\n",
+ action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c',
+ 0,0);
+ sessionID = op->o_time;
+ }
WRITE_INT32(fp,NSLCD_VERSION);
WRITE_INT32(fp,action);
WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
- WRITE_INT32(fp,op->o_time);
+ WRITE_INT32(fp,sessionID);
return 0;
}
npw.bv_len = tmpint32;
Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(%s), %s\n",
- pi.dn.bv_val,pi.uid.bv_val,0);
+ pi.dn.bv_val ? pi.dn.bv_val : "NULL",
+ pi.uid.bv_val ? pi.uid.bv_val : "NULL" ,0);
BER_BVZERO(&pi.msg);
+ pi.ispwdmgr = 0;
+
+ /* nssov_pam prohibits password mod */
+ if (!BER_BVISEMPTY(&ni->ni_pam_password_prohibit_message)) {
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(): %s (%s)\n",
+ "password_prohibit_message",
+ ni->ni_pam_password_prohibit_message.bv_val,0);
+ ber_str2bv(ni->ni_pam_password_prohibit_message.bv_val, 0, 0, &pi.msg);
+ rc = NSLCD_PAM_PERM_DENIED;
+ goto done;
+ }
- /* This is a prelim check */
if (BER_BVISEMPTY(&pi.dn)) {
- rc = pam_do_bind(ni,fp,op,&pi);
- if (rc == NSLCD_PAM_IGNORE)
- rc = NSLCD_PAM_SUCCESS;
+ /* should not be here at all, pam_authc() should have returned */
+ /* error */
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(), %s\n",
+ "prelim checking failed", 0, 0);
+ ber_str2bv("no pwmod requesting dn", 0, 0, &pi.msg);
+ rc = NSLCD_PAM_PERM_DENIED;
+ goto done;
+ }
+
+ if (BER_BVISEMPTY(&ni->ni_pam_pwdmgr_dn)) {
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(), %s\n",
+ "pwdmgr not configured", 0, 0);
+ ber_str2bv("pwdmgr not configured", 0, 0, &pi.msg);
+ rc = NSLCD_PAM_PERM_DENIED;
+ goto done;
+ } else if (!ber_bvcmp(&pi.dn, &ni->ni_pam_pwdmgr_dn)) {
+ /* root user requesting pwmod, convert uid to dn */
+ pi.ispwdmgr = 1;
+ rc = pam_uid2dn(ni, op, &pi);
+ if (rc) {
+ ber_str2bv("unable to convert uid to dn", 0, 0, &pi.msg);
+ rc = NSLCD_PAM_PERM_DENIED;
+ goto done;
+ }
+ }
+
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ struct berval bv;
+ SlapReply rs = {REP_RESULT};
+ slap_callback cb = {0};
+
+ ber_init_w_nullc(ber, LBER_USE_DER);
+ ber_printf(ber, "{");
+ if (!BER_BVISEMPTY(&pi.dn))
+ ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
+ &pi.dn);
+ /* supply old pwd only when end-user changing pwd */
+ if (!BER_BVISEMPTY(&pi.pwd) && pi.ispwdmgr == 0)
+ ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD,
+ &pi.pwd);
+ if (!BER_BVISEMPTY(&npw))
+ ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW,
+ &npw);
+ ber_printf(ber, "N}");
+ ber_flatten2(ber, &bv, 0);
+ op->o_tag = LDAP_REQ_EXTENDED;
+ op->ore_reqoid = slap_EXOP_MODIFY_PASSWD;
+ op->ore_reqdata = &bv;
+
+ if (pi.ispwdmgr) {
+ /* root user changing end-user passwords */
+ op->o_dn = ni->ni_pam_pwdmgr_dn;
+ op->o_ndn = ni->ni_pam_pwdmgr_dn;
} else {
- BerElementBuffer berbuf;
- BerElement *ber = (BerElement *)&berbuf;
- struct berval bv;
- SlapReply rs = {REP_RESULT};
- slap_callback cb = {0};
-
- ber_init_w_nullc(ber, LBER_USE_DER);
- ber_printf(ber, "{");
- if (!BER_BVISEMPTY(&pi.pwd))
- ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD,
- &pi.pwd);
- if (!BER_BVISEMPTY(&npw))
- ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW,
- &npw);
- ber_printf(ber, "N}");
- ber_flatten2(ber, &bv, 0);
- op->o_tag = LDAP_REQ_EXTENDED;
- op->ore_reqoid = slap_EXOP_MODIFY_PASSWD;
- op->ore_reqdata = &bv;
+ /* end-user self-pwd-mod */
op->o_dn = pi.dn;
op->o_ndn = pi.dn;
- op->o_callback = &cb;
- op->o_conn->c_authz_backend = op->o_bd;
- cb.sc_response = slap_null_cb;
- op->o_bd = frontendDB;
- rc = op->o_bd->be_extended(op, &rs);
- if (rs.sr_text)
- ber_str2bv(rs.sr_text, 0, 0, &pi.msg);
- if (rc == LDAP_SUCCESS)
- rc = NSLCD_PAM_SUCCESS;
- else
- rc = NSLCD_PAM_PERM_DENIED;
}
+ op->o_callback = &cb;
+ op->o_conn->c_authz_backend = op->o_bd;
+ cb.sc_response = slap_null_cb;
+ op->o_bd = frontendDB;
+ rc = op->o_bd->be_extended(op, &rs);
+ if (rs.sr_text)
+ ber_str2bv(rs.sr_text, 0, 0, &pi.msg);
+ if (rc == LDAP_SUCCESS)
+ rc = NSLCD_PAM_SUCCESS;
+ else
+ rc = NSLCD_PAM_PERM_DENIED;
+
+done:;
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(), rc (%d)\n", rc, 0, 0);
WRITE_INT32(fp,NSLCD_VERSION);
WRITE_INT32(fp,NSLCD_ACTION_PAM_PWMOD);
WRITE_INT32(fp,NSLCD_RESULT_BEGIN);