int pam_do_bind(nssov_info *ni,TFILE *fp,Operation *op, struct paminfo *pi) { int rc; slap_callback cb = {0}; SlapReply rs = {REP_RESULT}; 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 (BER_BVISEMPTY(&pi->pwd)) { rc = NSLCD_PAM_IGNORE; 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; op->o_dn.bv_val[0] = 0; op->o_dn.bv_len = 0; op->o_ndn.bv_val[0] = 0; op->o_ndn.bv_len = 0; op->o_tag = LDAP_REQ_BIND; op->o_protocol = LDAP_VERSION3; op->orb_method = LDAP_AUTH_SIMPLE; op->orb_cred = pi->pwd; op->o_req_dn = pi->dn; op->o_req_ndn = pi->dn; slap_op_time( &op->o_time, &op->o_tincr ); rc = op->o_bd->be_bind( op, &rs ); memset(pi->pwd.bv_val,0,pi->pwd.bv_len); /* quirk: on successful bind, caller has to send result. we need * to make sure callbacks run. */ if (rc == LDAP_SUCCESS) send_ldap_result(op, &rs); switch(rs.sr_err) { case LDAP_SUCCESS: rc = NSLCD_PAM_SUCCESS; break; case LDAP_INVALID_CREDENTIALS: rc = NSLCD_PAM_AUTH_ERR; break; default: rc = NSLCD_PAM_AUTH_ERR; break; } finish: return rc; }
Operation * slap_op_alloc( BerElement *ber, ber_int_t msgid, ber_tag_t tag, ber_int_t id, void *ctx ) { Operation *op = NULL; if ( ctx ) { void *otmp = NULL; ldap_pvt_thread_pool_getkey( ctx, (void *)slap_op_free, &otmp, NULL ); if ( otmp ) { op = otmp; otmp = LDAP_STAILQ_NEXT( op, o_next ); ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, otmp, slap_op_q_destroy, NULL, NULL ); op->o_abandon = 0; op->o_cancel = 0; } } if (!op) { op = (Operation *) ch_calloc( 1, sizeof(OperationBuffer) ); op->o_hdr = &((OperationBuffer *) op)->ob_hdr; op->o_controls = ((OperationBuffer *) op)->ob_controls; } op->o_ber = ber; op->o_msgid = msgid; op->o_tag = tag; slap_op_time( &op->o_time, &op->o_tincr ); op->o_opid = id; #if defined( LDAP_SLAPI ) if ( slapi_plugins_used ) { slapi_int_create_object_extensions( SLAPI_X_EXT_OPERATION, op ); } #endif /* defined( LDAP_SLAPI ) */ return( op ); }
static int slap_auxprop_store( void *glob_context, sasl_server_params_t *sparams, struct propctx *prctx, const char *user, unsigned ulen) { Operation op = {0}; Opheader oph; int rc, i; unsigned j; Connection *conn = NULL; const struct propval *pr; Modifications *modlist = NULL, **modtail = &modlist, *mod; slap_callback cb = { NULL, slap_null_cb, NULL, NULL }; char textbuf[SLAP_TEXT_BUFLEN]; const char *text; size_t textlen = sizeof(textbuf); #ifdef SLAP_AUXPROP_DONTUSECOPY int dontUseCopy = 0; BackendDB *dontUseCopy_bd = NULL; #endif /* SLAP_AUXPROP_DONTUSECOPY */ /* just checking if we are enabled */ if (!prctx) return SASL_OK; if (!sparams || !user) return SASL_BADPARAM; pr = sparams->utils->prop_get( sparams->propctx ); /* Find our DN and conn first */ for( i = 0; pr[i].name; i++ ) { if ( pr[i].name[0] == '*' ) { if ( !strcmp( pr[i].name, slap_propnames[SLAP_SASL_PROP_CONN] ) ) { if ( pr[i].values && pr[i].values[0] ) AC_MEMCPY( &conn, pr[i].values[0], sizeof( conn ) ); continue; } if ( !strcmp( pr[i].name, slap_propnames[SLAP_SASL_PROP_AUTHCLEN] )) { if ( pr[i].values && pr[i].values[0] ) AC_MEMCPY( &op.o_req_ndn.bv_len, pr[i].values[0], sizeof( op.o_req_ndn.bv_len ) ); } else if ( !strcmp( pr[i].name, slap_propnames[SLAP_SASL_PROP_AUTHC] ) ) { if ( pr[i].values ) op.o_req_ndn.bv_val = (char *)pr[i].values[0]; } #ifdef SLAP_AUXPROP_DONTUSECOPY if ( slap_dontUseCopy_propnames != NULL ) { struct berval bv; ber_str2bv( &pr[i].name[1], 0, 1, &bv ); for ( j = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ j ] ); j++ ) { if ( bvmatch( &bv, &slap_dontUseCopy_propnames[ j ] ) ) { dontUseCopy = 1; break; } } } #endif /* SLAP_AUXPROP_DONTUSECOPY */ } } if (!conn || !op.o_req_ndn.bv_val) return SASL_BADPARAM; op.o_bd = select_backend( &op.o_req_ndn, 1 ); if ( !op.o_bd || !op.o_bd->be_modify ) return SASL_FAIL; #ifdef SLAP_AUXPROP_DONTUSECOPY if ( SLAP_SHADOW( op.o_bd ) && dontUseCopy ) { dontUseCopy_bd = op.o_bd; op.o_bd = frontendDB; op.o_dontUseCopy = SLAP_CONTROL_CRITICAL; } #endif /* SLAP_AUXPROP_DONTUSECOPY */ pr = sparams->utils->prop_get( prctx ); if (!pr) return SASL_BADPARAM; for (i=0; pr[i].name; i++); if (!i) return SASL_BADPARAM; for (i=0; pr[i].name; i++) { mod = (Modifications *)ch_malloc( sizeof(Modifications) ); mod->sml_op = LDAP_MOD_REPLACE; mod->sml_flags = 0; ber_str2bv( pr[i].name, 0, 0, &mod->sml_type ); mod->sml_numvals = pr[i].nvalues; mod->sml_values = (struct berval *)ch_malloc( (pr[i].nvalues + 1) * sizeof(struct berval)); for (j=0; j<pr[i].nvalues; j++) { ber_str2bv( pr[i].values[j], 0, 1, &mod->sml_values[j]); } BER_BVZERO( &mod->sml_values[j] ); mod->sml_nvalues = NULL; mod->sml_desc = NULL; *modtail = mod; modtail = &mod->sml_next; } *modtail = NULL; rc = slap_mods_check( &op, modlist, &text, textbuf, textlen, NULL ); if ( rc == LDAP_SUCCESS ) { rc = slap_mods_no_user_mod_check( &op, modlist, &text, textbuf, textlen ); if ( rc == LDAP_SUCCESS ) { if ( conn->c_sasl_bindop ) { op.o_hdr = conn->c_sasl_bindop->o_hdr; } else { op.o_hdr = &oph; memset( &oph, 0, sizeof(oph) ); operation_fake_init( conn, &op, ldap_pvt_thread_pool_context(), 0 ); } op.o_tag = LDAP_REQ_MODIFY; op.o_ndn = op.o_req_ndn; op.o_callback = &cb; slap_op_time( &op.o_time, &op.o_tincr ); op.o_do_not_cache = 1; op.o_is_auth_check = 1; op.o_req_dn = op.o_req_ndn; op.orm_modlist = modlist; for (;;) { SlapReply rs = {REP_RESULT}; rc = op.o_bd->be_modify( &op, &rs ); #ifdef SLAP_AUXPROP_DONTUSECOPY if ( dontUseCopy && rs.sr_err == LDAP_UNAVAILABLE && slap_dontUseCopy_ignore ) { op.o_bd = dontUseCopy_bd; op.o_dontUseCopy = SLAP_CONTROL_NONE; dontUseCopy = 0; continue; } #endif /* SLAP_AUXPROP_DONTUSECOPY */ break; } } } slap_mods_free( modlist, 1 ); return rc != LDAP_SUCCESS ? SASL_FAIL : SASL_OK; }
static int #else static void #endif slap_auxprop_lookup( void *glob_context, sasl_server_params_t *sparams, unsigned flags, const char *user, unsigned ulen) { OperationBuffer opbuf = {{ NULL }}; Operation *op = (Operation *)&opbuf; int i, doit = 0; Connection *conn = NULL; lookup_info sl; int rc = LDAP_SUCCESS; #ifdef SLAP_AUXPROP_DONTUSECOPY int dontUseCopy = 0; BackendDB *dontUseCopy_bd = NULL; #endif /* SLAP_AUXPROP_DONTUSECOPY */ sl.list = sparams->utils->prop_get( sparams->propctx ); sl.sparams = sparams; sl.flags = flags; /* Find our DN and conn first */ for( i = 0; sl.list[i].name; i++ ) { if ( sl.list[i].name[0] == '*' ) { if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_CONN] ) ) { if ( sl.list[i].values && sl.list[i].values[0] ) AC_MEMCPY( &conn, sl.list[i].values[0], sizeof( conn ) ); continue; } if ( flags & SASL_AUXPROP_AUTHZID ) { if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZLEN] )) { if ( sl.list[i].values && sl.list[i].values[0] ) AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0], sizeof( op->o_req_ndn.bv_len ) ); } else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZ] )) { if ( sl.list[i].values ) op->o_req_ndn.bv_val = (char *)sl.list[i].values[0]; break; } } if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHCLEN] )) { if ( sl.list[i].values && sl.list[i].values[0] ) AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0], sizeof( op->o_req_ndn.bv_len ) ); } else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHC] ) ) { if ( sl.list[i].values ) { op->o_req_ndn.bv_val = (char *)sl.list[i].values[0]; if ( !(flags & SASL_AUXPROP_AUTHZID) ) break; } } #ifdef SLAP_AUXPROP_DONTUSECOPY if ( slap_dontUseCopy_propnames != NULL ) { int j; struct berval bv; ber_str2bv( &sl.list[i].name[1], 0, 1, &bv ); for ( j = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ j ]); j++ ) { if ( bvmatch( &bv, &slap_dontUseCopy_propnames[ j ] ) ) { dontUseCopy = 1; break; } } } #endif /* SLAP_AUXPROP_DONTUSECOPY */ } } /* Now see what else needs to be fetched */ for( i = 0; sl.list[i].name; i++ ) { const char *name = sl.list[i].name; if ( name[0] == '*' ) { if ( flags & SASL_AUXPROP_AUTHZID ) continue; /* Skip our private properties */ if ( !strcmp( name, slap_propnames[0] )) { i += SLAP_SASL_PROP_COUNT - 1; continue; } name++; } else if ( !(flags & SASL_AUXPROP_AUTHZID ) ) continue; if ( sl.list[i].values ) { if ( !(flags & SASL_AUXPROP_OVERRIDE) ) continue; } doit = 1; break; } if (doit) { slap_callback cb = { NULL, sasl_ap_lookup, NULL, NULL }; cb.sc_private = &sl; op->o_bd = select_backend( &op->o_req_ndn, 1 ); if ( op->o_bd ) { /* For rootdn, see if we can use the rootpw */ if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) && !BER_BVISEMPTY( &op->o_bd->be_rootpw )) { struct berval cbv = BER_BVNULL; /* If there's a recognized scheme, see if it's CLEARTEXT */ if ( lutil_passwd_scheme( op->o_bd->be_rootpw.bv_val )) { if ( !strncasecmp( op->o_bd->be_rootpw.bv_val, sc_cleartext.bv_val, sc_cleartext.bv_len )) { /* If it's CLEARTEXT, skip past scheme spec */ cbv.bv_len = op->o_bd->be_rootpw.bv_len - sc_cleartext.bv_len; if ( cbv.bv_len ) { cbv.bv_val = op->o_bd->be_rootpw.bv_val + sc_cleartext.bv_len; } } /* No scheme, use the whole value */ } else { cbv = op->o_bd->be_rootpw; } if ( !BER_BVISEMPTY( &cbv )) { for( i = 0; sl.list[i].name; i++ ) { const char *name = sl.list[i].name; if ( name[0] == '*' ) { if ( flags & SASL_AUXPROP_AUTHZID ) continue; name++; } else if ( !(flags & SASL_AUXPROP_AUTHZID ) ) continue; if ( !strcasecmp(name,"userPassword") ) { sl.sparams->utils->prop_set( sl.sparams->propctx, sl.list[i].name, cbv.bv_val, cbv.bv_len ); break; } } } } #ifdef SLAP_AUXPROP_DONTUSECOPY if ( SLAP_SHADOW( op->o_bd ) && dontUseCopy ) { dontUseCopy_bd = op->o_bd; op->o_bd = frontendDB; } retry_dontUseCopy:; #endif /* SLAP_AUXPROP_DONTUSECOPY */ if ( op->o_bd->be_search ) { SlapReply rs = {REP_RESULT}; #ifdef SLAP_AUXPROP_DONTUSECOPY LDAPControl **save_ctrls = NULL, c; int save_dontUseCopy; #endif /* SLAP_AUXPROP_DONTUSECOPY */ op->o_hdr = conn->c_sasl_bindop->o_hdr; op->o_controls = opbuf.ob_controls; op->o_tag = LDAP_REQ_SEARCH; op->o_dn = conn->c_ndn; op->o_ndn = conn->c_ndn; op->o_callback = &cb; slap_op_time( &op->o_time, &op->o_tincr ); op->o_do_not_cache = 1; op->o_is_auth_check = 1; op->o_req_dn = op->o_req_ndn; op->ors_scope = LDAP_SCOPE_BASE; op->ors_deref = LDAP_DEREF_NEVER; op->ors_tlimit = SLAP_NO_LIMIT; op->ors_slimit = 1; op->ors_filter = &generic_filter; op->ors_filterstr = generic_filterstr; op->o_authz = conn->c_authz; /* FIXME: we want all attributes, right? */ op->ors_attrs = NULL; #ifdef SLAP_AUXPROP_DONTUSECOPY if ( dontUseCopy ) { save_dontUseCopy = op->o_dontUseCopy; if ( !op->o_dontUseCopy ) { int cnt = 0; save_ctrls = op->o_ctrls; if ( op->o_ctrls ) { for ( ; op->o_ctrls[ cnt ]; cnt++ ) ; } op->o_ctrls = op->o_tmpcalloc( sizeof(LDAPControl *), cnt + 2, op->o_tmpmemctx ); if ( cnt ) { for ( cnt = 0; save_ctrls[ cnt ]; cnt++ ) { op->o_ctrls[ cnt ] = save_ctrls[ cnt ]; } } c.ldctl_oid = LDAP_CONTROL_DONTUSECOPY; c.ldctl_iscritical = 1; BER_BVZERO( &c.ldctl_value ); op->o_ctrls[ cnt ] = &c; } op->o_dontUseCopy = SLAP_CONTROL_CRITICAL; } #endif /* SLAP_AUXPROP_DONTUSECOPY */ rc = op->o_bd->be_search( op, &rs ); #ifdef SLAP_AUXPROP_DONTUSECOPY if ( dontUseCopy ) { if ( save_ctrls != op->o_ctrls ) { op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx ); op->o_ctrls = save_ctrls; op->o_dontUseCopy = save_dontUseCopy; } if ( rs.sr_err == LDAP_UNAVAILABLE && slap_dontUseCopy_ignore ) { op->o_bd = dontUseCopy_bd; dontUseCopy = 0; goto retry_dontUseCopy; } } #endif /* SLAP_AUXPROP_DONTUSECOPY */ } } } #if SASL_VERSION_FULL >= 0x020118 return rc != LDAP_SUCCESS ? SASL_FAIL : SASL_OK; #endif }
static int #else static void #endif slap_auxprop_lookup( void *glob_context, sasl_server_params_t *sparams, unsigned flags, const char *user, unsigned ulen) { OperationBuffer opbuf = {{ NULL }}; Operation *op = (Operation *)&opbuf; int i, doit = 0; Connection *conn = NULL; lookup_info sl; int rc = LDAP_SUCCESS; sl.list = sparams->utils->prop_get( sparams->propctx ); sl.sparams = sparams; sl.flags = flags; /* Find our DN and conn first */ for( i = 0; sl.list[i].name; i++ ) { if ( sl.list[i].name[0] == '*' ) { if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_CONN] ) ) { if ( sl.list[i].values && sl.list[i].values[0] ) AC_MEMCPY( &conn, sl.list[i].values[0], sizeof( conn ) ); continue; } if ( flags & SASL_AUXPROP_AUTHZID ) { if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZLEN] )) { if ( sl.list[i].values && sl.list[i].values[0] ) AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0], sizeof( op->o_req_ndn.bv_len ) ); } else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZ] )) { if ( sl.list[i].values ) op->o_req_ndn.bv_val = (char *)sl.list[i].values[0]; break; } } if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHCLEN] )) { if ( sl.list[i].values && sl.list[i].values[0] ) AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0], sizeof( op->o_req_ndn.bv_len ) ); } else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHC] ) ) { if ( sl.list[i].values ) { op->o_req_ndn.bv_val = (char *)sl.list[i].values[0]; if ( !(flags & SASL_AUXPROP_AUTHZID) ) break; } } } } /* we don't know anything about this, ignore it */ if ( !conn ) { rc = LDAP_SUCCESS; goto done; } /* Now see what else needs to be fetched */ for( i = 0; sl.list[i].name; i++ ) { const char *name = sl.list[i].name; if ( name[0] == '*' ) { if ( flags & SASL_AUXPROP_AUTHZID ) continue; /* Skip our private properties */ if ( !strcmp( name, slap_propnames[0] )) { i += SLAP_SASL_PROP_COUNT - 1; continue; } name++; } else if ( !(flags & SASL_AUXPROP_AUTHZID ) ) continue; if ( sl.list[i].values ) { if ( !(flags & SASL_AUXPROP_OVERRIDE) ) continue; } doit = 1; break; } if (doit) { slap_callback cb = { NULL, sasl_ap_lookup, NULL, NULL }; cb.sc_private = &sl; op->o_bd = select_backend( &op->o_req_ndn, 1 ); if ( op->o_bd ) { /* For rootdn, see if we can use the rootpw */ if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) && !BER_BVISEMPTY( &op->o_bd->be_rootpw )) { struct berval cbv = BER_BVNULL; /* If there's a recognized scheme, see if it's CLEARTEXT */ if ( lutil_passwd_scheme( op->o_bd->be_rootpw.bv_val )) { if ( !strncasecmp( op->o_bd->be_rootpw.bv_val, sc_cleartext.bv_val, sc_cleartext.bv_len )) { /* If it's CLEARTEXT, skip past scheme spec */ cbv.bv_len = op->o_bd->be_rootpw.bv_len - sc_cleartext.bv_len; if ( cbv.bv_len ) { cbv.bv_val = op->o_bd->be_rootpw.bv_val + sc_cleartext.bv_len; } } /* No scheme, use the whole value */ } else { cbv = op->o_bd->be_rootpw; } if ( !BER_BVISEMPTY( &cbv )) { for( i = 0; sl.list[i].name; i++ ) { const char *name = sl.list[i].name; if ( name[0] == '*' ) { if ( flags & SASL_AUXPROP_AUTHZID ) continue; name++; } else if ( !(flags & SASL_AUXPROP_AUTHZID ) ) continue; if ( !strcasecmp(name,"userPassword") ) { sl.sparams->utils->prop_set( sl.sparams->propctx, sl.list[i].name, cbv.bv_val, cbv.bv_len ); break; } } } } if ( op->o_bd->be_search ) { SlapReply rs = {REP_RESULT}; op->o_hdr = conn->c_sasl_bindop->o_hdr; op->o_controls = opbuf.ob_controls; op->o_tag = LDAP_REQ_SEARCH; op->o_dn = conn->c_ndn; op->o_ndn = conn->c_ndn; op->o_callback = &cb; slap_op_time( &op->o_time, &op->o_tincr ); op->o_do_not_cache = 1; op->o_is_auth_check = 1; op->o_req_dn = op->o_req_ndn; op->ors_scope = LDAP_SCOPE_BASE; op->ors_deref = LDAP_DEREF_NEVER; op->ors_tlimit = SLAP_NO_LIMIT; op->ors_slimit = 1; op->ors_filter = &generic_filter; op->ors_filterstr = generic_filterstr; op->o_authz = conn->c_authz; /* FIXME: we want all attributes, right? */ op->ors_attrs = NULL; rc = op->o_bd->be_search( op, &rs ); } } } done:; #if SASL_VERSION_FULL >= 0x020118 return rc != LDAP_SUCCESS ? SASL_FAIL : SASL_OK; #endif }
static int pam_sess(nssov_info *ni,TFILE *fp,Operation *op,int action) { struct berval dn, uid, svc, tty, rhost, ruser; int32_t tmpint32; char dnc[1024]; char svcc[256]; char uidc[32]; char ttyc[32]; char rhostc[256]; char ruserc[32]; slap_callback cb = {0}; SlapReply rs = {REP_RESULT}; char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE]; struct berval timestamp, bv[2], *nbv; time_t stamp; Modifications mod; READ_STRING(fp,uidc); uid.bv_val = uidc; uid.bv_len = tmpint32; READ_STRING(fp,dnc); dn.bv_val = dnc; dn.bv_len = tmpint32; READ_STRING(fp,svcc); svc.bv_val = svcc; svc.bv_len = tmpint32; READ_STRING(fp,ttyc); tty.bv_val = ttyc; tty.bv_len = tmpint32; READ_STRING(fp,rhostc); rhost.bv_val = rhostc; rhost.bv_len = tmpint32; READ_STRING(fp,ruserc); ruser.bv_val = ruserc; ruser.bv_len = tmpint32; READ_INT32(fp,stamp); 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; { int i, found=0; for (i=0; !BER_BVISNULL(&ni->ni_pam_sessions[i]); i++) { if (ni->ni_pam_sessions[i].bv_len != svc.bv_len) continue; if (!strcasecmp(ni->ni_pam_sessions[i].bv_val, svc.bv_val)) { found = 1; break; } } if (!found) return 0; } slap_op_time( &op->o_time, &op->o_tincr ); timestamp.bv_len = sizeof(timebuf); timestamp.bv_val = timebuf; if (action == NSLCD_ACTION_PAM_SESS_O ) stamp = op->o_time; slap_timestamp( &stamp, ×tamp ); bv[0].bv_len = timestamp.bv_len + global_host_bv.bv_len + svc.bv_len + tty.bv_len + ruser.bv_len + rhost.bv_len + STRLENOF(" (@)"); bv[0].bv_val = op->o_tmpalloc( bv[0].bv_len+1, op->o_tmpmemctx ); 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); mod.sml_numvals = 1; mod.sml_values = bv; BER_BVZERO(&bv[1]); attr_normalize( ad_loginStatus, bv, &nbv, op->o_tmpmemctx ); mod.sml_nvalues = nbv; mod.sml_desc = ad_loginStatus; mod.sml_op = action == NSLCD_ACTION_PAM_SESS_O ? LDAP_MOD_ADD : LDAP_MOD_DELETE; mod.sml_flags = SLAP_MOD_INTERNAL; mod.sml_next = NULL; cb.sc_response = slap_null_cb; op->o_callback = &cb; op->o_tag = LDAP_REQ_MODIFY; op->o_dn = op->o_bd->be_rootdn; op->o_ndn = op->o_bd->be_rootndn; op->orm_modlist = &mod; op->orm_no_opattrs = 1; op->o_req_dn = dn; op->o_req_ndn = dn; op->o_bd->be_modify( op, &rs ); if ( mod.sml_next ) { slap_mods_free( mod.sml_next, 1 ); } ber_bvarray_free_x( nbv, op->o_tmpmemctx ); WRITE_INT32(fp,NSLCD_VERSION); WRITE_INT32(fp,action); WRITE_INT32(fp,NSLCD_RESULT_BEGIN); WRITE_INT32(fp,op->o_time); return 0; }