ruby-ldap-0.9.16/0000755000004100000410000000000012260553635013545 5ustar www-datawww-dataruby-ldap-0.9.16/clientauth.c0000644000004100000410000004435212260553634016060 0ustar www-datawww-data/* * clientauth.c * Composed by Yuri Arabadji @ Fused Network * * bugs only: yuri[.@.]deepunix.net */ #include "ruby.h" #include "rbldap.h" #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #ifdef USE_SSL_CLIENTAUTH #warning ######################################################## #warning #warning " Enabling highly experimental code. " #warning "Expect breakage, ice melting, floods and world terror." #warning #warning ######################################################## #include #include #include #include // helpful macros #define LDAPTOOL_RESULT_IS_AN_ERROR( rc ) \ ( (rc) != LDAP_SUCCESS && (rc) != LDAP_COMPARE_TRUE \ && (rc) != LDAP_COMPARE_FALSE ) /* copied from ldaprot.h - required to parse the pwpolicy ctrl */ #define LDAP_TAG_PWP_WARNING 0xA0L /* context specific + constructed */ #define LDAP_TAG_PWP_SECSLEFT 0x80L /* context specific + primitive */ #define LDAP_TAG_PWP_GRCLOGINS 0x81L /* context specific + primitive + 1 */ #define LDAP_TAG_PWP_ERROR 0x81L /* context specific + primitive + 1 */ // checks for *SSL* error #define Check_LDAP_Error_MSG(retval, errmsg) { \ if( (long)(retval) == LDAP_OPT_ERROR ){ \ rb_raise(rb_eLDAP_ResultError, "%s. Lower layer reported: %s.", errmsg, ldapssl_err2string(PORT_GetError())); \ } \ } //////////////////////////////////////////////////////////////////////////////// VALUE rb_cLDAP_SSLAuthConn; // forward declare 'em VALUE rb_ldap_sslauthconn_initialize(int, VALUE[], VALUE); void ldaptool_print_referrals(char**); void print_to_stdout(char*, ...); void handle_sigint(int, siginfo_t*, void*); //////////////////////////////////////////////////////////////////////////////// // // Thank you, ldaptool / common.c! // //////////////////////////////////////////////////////////////////////////////// /* * Wait for a result, check for and display errors and referrals. * Also recognize and display "Unsolicited notification" messages. * Returns an LDAP error code. */ int wait4result(LDAP *ld, int msgid, struct berval **servercredp, char *msg) { LDAPMessage *res; int rc, received_only_unsolicited = 1; while (received_only_unsolicited) { res = NULL; if ((rc = ldap_result(ld, msgid, 1, (struct timeval *) NULL, &res)) == LDAP_OPT_ERROR) { return ldaptool_print_lderror(ld, msg); } /* * Special handling for unsolicited notifications: * 1. Parse and display contents. * 2. go back and wait for another (real) result. */ if (rc == LDAP_RES_EXTENDED && ldap_msgid(res) == LDAP_RES_UNSOLICITED) { rc = ldaptool_print_extended_response(ld, res, "Unsolicited response"); } else { rc = parse_result(ld, res, servercredp, msg, 1); received_only_unsolicited = 0; /* we're done */ } } return ( rc); } /* * print contents of an extended response to stderr * this is mainly to support unsolicited notifications * Returns an LDAP error code (from the extended result). */ int ldaptool_print_extended_response( LDAP *ld, LDAPMessage *res, char *msg ) { char *oid; struct berval *data; if ( ldap_parse_extended_result( ld, res, &oid, &data, 0 ) != LDAP_SUCCESS ) { ldaptool_print_lderror( ld, msg); } else { if ( oid != NULL ) { if ( strcmp ( oid, LDAP_NOTICE_OF_DISCONNECTION ) == 0 ) { print_to_stdout("%s: Notice of Disconnection\n", msg); } else { print_to_stdout("%s: OID %s\n", msg, oid); } ldap_memfree( oid ); } else { print_to_stdout("%s: missing OID\n", msg); } if ( data != NULL ) { print_to_stdout("%s: Data (length %d):\n", msg, data->bv_len ); #if 0 /* XXXmcs: maybe we should display the actual data? */ lber_bprint( data->bv_val, data->bv_len ); #endif ber_bvfree( data ); } } return parse_result( ld, res, NULL, msg, 1 ); } int parse_result(LDAP *ld, LDAPMessage *res, struct berval **servercredp, char *msg, int freeit) { int rc, lderr, errno; char **refs = NULL; LDAPControl **ctrls; if ((rc = ldap_parse_result(ld, res, &lderr, NULL, NULL, &refs, &ctrls, 0)) != LDAP_SUCCESS) { (void) ldaptool_print_lderror(ld, msg); ldap_msgfree(res); return ( rc); } if ((rc = check_response_controls(ld, msg, ctrls, 1)) != LDAP_SUCCESS) { ldap_msgfree(res); return ( rc); } if (servercredp != NULL && (rc = ldap_parse_sasl_bind_result(ld, res, servercredp, 0)) != LDAP_SUCCESS) { (void) ldaptool_print_lderror(ld, msg); ldap_msgfree(res); return ( rc); } if (freeit) { ldap_msgfree(res); } if (LDAPTOOL_RESULT_IS_AN_ERROR(lderr)) { (void) ldaptool_print_lderror(ld, msg); } if (refs != NULL) { ldaptool_print_referrals(refs); ldap_value_free(refs); } return ( lderr); } /* * check for response controls. authentication response control * and PW POLICY control are the ones we care about right now. */ int check_response_controls(LDAP *ld, char *msg, LDAPControl **ctrls, int freeit) { int i; int errno; int pw_days = 0, pw_hrs = 0, pw_mins = 0, pw_secs = 0; /* for pwpolicy */ char *s = NULL; BerElement *ber = NULL; static const char *pwpolicy_err2str[] = { "Password has expired.", "Account is locked.", "Password has been reset by an administrator; you must change it.", "Password change not allowed.", "Must supply old password.", "Invalid password syntax.", "Password too short.", "Password too young.", "Password in history." }; if (NULL != ctrls) { for (i = 0; NULL != ctrls[i]; ++i) { if (0 == strcmp(ctrls[i]->ldctl_oid, LDAP_CONTROL_AUTH_RESPONSE)) { s = ctrls[i]->ldctl_value.bv_val; if (NULL == s) { s = "Null"; } else if (*s == '\0') { s = "Anonymous"; } print_to_stdout("%s: bound as %s\n", msg, s); } /* end of LDAP_CONTROL_AUTH_RESPONSE */ if (0 == strcmp(ctrls[i]->ldctl_oid, LDAP_CONTROL_PWEXPIRING)) { /* Warn the user his passwd is to expire */ errno = 0; pw_secs = atoi(ctrls[i]->ldctl_value.bv_val); if (pw_secs > 0 && errno != ERANGE) { if (pw_secs > 86400) { pw_days = (pw_secs / 86400); pw_secs = (pw_secs % 86400); } if (pw_secs > 3600) { pw_hrs = (pw_secs / 3600); pw_secs = (pw_secs % 3600); } if (pw_secs > 60) { pw_mins = (pw_secs / 60); pw_secs = (pw_secs % 60); } printf("%s: Warning ! Your password will expire after ", msg); if (pw_days) { printf("%d days, ", pw_days); } if (pw_hrs) { printf("%d hrs, ", pw_hrs); } if (pw_mins) { printf("%d mins, ", pw_mins); } printf("%d seconds.\n", pw_secs); } } /* end of LDAP_CONTROL_PWEXPIRING */ if (0 == strcmp(ctrls[i]->ldctl_oid, LDAP_X_CONTROL_PWPOLICY_RESPONSE)) { ber_tag_t tag1 = 0, tag2 = 0, tag3 = 0; ber_int_t warnvalue = 0; int grclogins = -1, secsleft = -1; ber_int_t errvalue = -1; static int err2str_size = sizeof (pwpolicy_err2str) / sizeof (pwpolicy_err2str[0]); if ((ber = ber_init(&(ctrls[i]->ldctl_value))) == NULL) { fprintf(stderr, "%s: not enough memory\n", msg); return ( LDAP_NO_MEMORY); } if (ber_scanf(ber, "{t", &tag1) == LBER_ERROR) { /* error */ ber_free(ber, 1); return (ldaptool_print_lderror(ld, msg)); } switch (tag1) { case LDAP_TAG_PWP_WARNING: if (ber_scanf(ber, "{ti}", &tag2, &warnvalue) == LBER_ERROR) { /* error */ ber_free(ber, 1); return (ldaptool_print_lderror(ld, msg)); } switch (tag2) { case LDAP_TAG_PWP_SECSLEFT: secsleft = (int) warnvalue; break; case LDAP_TAG_PWP_GRCLOGINS: grclogins = (int) warnvalue; break; default: /* error */ ber_free(ber, 1); return (ldaptool_print_lderror(ld, msg)); } /* Now check for the error value if it's present */ if (ber_scanf(ber, "te", &tag3, &errvalue) != LBER_ERROR) { if (tag3 != LDAP_TAG_PWP_ERROR) { errvalue = -1; } } break; case LDAP_TAG_PWP_ERROR: if (ber_scanf(ber, "e}", &errvalue) == LBER_ERROR) { /* error */ ber_free(ber, 1); return (ldaptool_print_lderror(ld, msg)); } break; default: /* error */ ber_free(ber, 1); return (ldaptool_print_lderror(ld, msg)); } /* Now we have all the values */ if (secsleft >= 0) { fprintf(stderr, "%s: Password will expire in %d seconds\n", msg, secsleft); } if (grclogins >= 0) { fprintf(stderr, "%s: %d grace login(s) remain\n", msg, grclogins); } if (errvalue >= 0 && errvalue < err2str_size) { fprintf(stderr, "%s: %s\n", msg, pwpolicy_err2str[errvalue]); } else if (errvalue != -1) { fprintf(stderr, "%s: %s\n", msg, "Invalid error value in password policy response control"); } } /* end of LDAP_X_CONTROL_PWPOLICY_RESPONSE */ } if (freeit) { ldap_controls_free(ctrls); ber_free(ber, 1); } } return LDAP_SUCCESS; } /* * Like ldap_sasl_bind_s() but calls wait4result() to display * any referrals returned and report errors in a consistent way. */ int ldaptool_sasl_bind_s(LDAP *ld, const char *dn, const char *mechanism, const struct berval *cred, LDAPControl **serverctrls, LDAPControl **clientctrls, struct berval **servercredp, char *msg) { int rc, msgid; if (servercredp != NULL) { *servercredp = NULL; } if ((rc = ldap_sasl_bind(ld, dn, mechanism, cred, serverctrls, clientctrls, &msgid)) == LDAP_SUCCESS) { rc = wait4result(ld, msgid, servercredp, msg); } return ( rc); } // Rebind in case we were unbound VALUE rb_ldap_sslauthconn_rebind(VALUE self) { VALUE ary = rb_iv_get (self, "@args"); return rb_ldap_sslauthconn_initialize(RARRAY_LEN(ary), RARRAY_PTR(ary), self); } //////////////////////////////////////////////////////////////////////////////// // // .bind // //////////////////////////////////////////////////////////////////////////////// /* * call-seq: * conn.bind(serverctrls = nil) {|conn| # optional block } * => self * * Bind a LDAP connection with SASL EXTERNAL method, * with optional +serverctls+. * If a block is given, +self+ is yielded to the block. */ VALUE rb_ldap_sslauthconn_s_bind(int argc, VALUE argv[], VALUE self) { RB_LDAP_DATA *ldapdata; VALUE arg1; LDAPControl **bindctrls = NULL; Data_Get_Struct(self, RB_LDAP_DATA, ldapdata); if (ldapdata->bind == 0) { if (rb_iv_get(self, "@args") != Qnil) { rb_ldap_sslauthconn_rebind(self); GET_LDAP_DATA(self, ldapdata); } else { rb_raise(rb_eLDAP_InvalidDataError, "The LDAP handler has already unbound."); } } else { rb_raise(rb_eLDAP_Error, "already bound."); }; switch (rb_scan_args(argc, argv, "01", &arg1)) { case 1: bindctrls = rb_ldap_get_controls(arg1); case 0: break; default: rb_bug("rb_ldap_sslauthconn_bind_s"); } ldapdata->err = ldaptool_sasl_bind_s(ldapdata->ldap, NULL, LDAP_SASL_EXTERNAL, NULL, bindctrls, NULL, NULL, "clientauth_ldap_sasl_bind"); Check_LDAP_Result(ldapdata->err); ldapdata->bind = 1; if (rb_block_given_p()) { rb_ensure(rb_yield, self, rb_ldap_conn_unbind, self); return Qnil; } else { return self; }; }; //////////////////////////////////////////////////////////////////////////////// // // .new // //////////////////////////////////////////////////////////////////////////////// VALUE rb_ldap_sslauthconn_initialize(int argc, VALUE argv[], VALUE self) { RB_LDAP_DATA *ldapdata; LDAP *cldap; char *chost = NULL; char *certpath = NULL; char *certname = NULL; char *keypass = NULL; int cport = LDAP_PORT; int ctls = 0; VALUE host, port, tls, cp, cn, key_pw, sctrls, cctrls; Data_Get_Struct(self, RB_LDAP_DATA, ldapdata); if (ldapdata->ldap) return Qnil; int anum = rb_scan_args(argc, argv, "62", &host, &port, &tls, &cp, &cn, &key_pw, &sctrls, &cctrls); if (anum < 6) { rb_bug("rb_ldap_auth_conn_new"); } else if (anum >= 6) { chost = StringValueCStr(host); cport = NUM2INT(port); ctls = (tls == Qtrue) ? 1 : 0; certpath = (cp == Qnil) ? NULL : StringValueCStr(cp); certname = (cn == Qnil) ? NULL : StringValueCStr(cn); keypass = (key_pw == Qnil) ? NULL : StringValueCStr(key_pw); } // Here we go Check_LDAP_Error_MSG(ldapssl_clientauth_init(certpath, NULL, (keypass == NULL) ? 0 : 1, NULL, NULL), "SSLAuthConn: Failed to initialize NSS certificate storeage. -- ldapssl_clientauth_init"); // Make sure we can SIGINT struct sigaction act = { .sa_sigaction = handle_sigint, .sa_flags = SA_RESTART | SA_SIGINFO }; if (sigaction(SIGINT, &act, NULL) < 0) { print_to_stdout("error setting sigint"); }; cldap = tls ? (LDAP*)prldap_init(chost, cport, 0) : ldapssl_init(chost, cport, 1); Check_LDAP_Error_MSG((long) cldap, "SSLAuthConn: Init failure"); Check_LDAP_Error_MSG(ldapssl_enable_clientauth(cldap, "", keypass, certname), "SSLAuthConn: Couldn't enable client auth"); if (tls) { Check_LDAP_Error_MSG(ldap_start_tls_s(cldap, NULL, NULL), "SSLAuthConn: TLS failure"); } // protect key char* ptr_orig = StringValuePtr(key_pw); char* iptr = ptr_orig; while ((iptr - ptr_orig <= 16) && ((char)*iptr != '\0')) { *iptr++ = 'X'; } // set ruby stuff ldapdata->ldap = cldap; rb_iv_set(self, "@args", rb_ary_new4(argc, argv)); return Qnil; } //////////////////////////////////////////////////////////////////////////////// // // Fancy printing stuff goes here // //////////////////////////////////////////////////////////////////////////////// /* * Print referrals to stdout */ void ldaptool_print_referrals(char **refs) { int i; if (refs != NULL) { for (i = 0; refs[ i ] != NULL; ++i) { print_to_stdout("Referral: %s\n", refs[i]); } } } /* * Retrieve and print an LDAP error message. Returns the LDAP error code. */ int ldaptool_print_lderror( LDAP *ld, char *msg) { int lderr = ldap_get_lderrno( ld, NULL, NULL ); ldap_perror(ld, msg); int sslerr = PORT_GetError(); rb_warn("%s SSL sublayer reported error: ", msg, ldapssl_err2string(sslerr)); return(lderr); } void print_to_stdout(char* format, ...) { static char buf[512] = ""; va_list ap; va_start(ap, format); vsnprintf(buf, sizeof(buf) - 1, format, ap); rb_io_write(rb_stdout, rb_str_new2(buf)); va_end(ap); } void handle_sigint(int sig, siginfo_t *siginfo, void *context) { print_to_stdout("Requested to terminate [%d].\n", sig); exit(0); } VALUE rb_ldap_sslauthconn_s_open(int argc, VALUE argv[], VALUE klass) { rb_notimplement(); } /* * call-seq: * LDAP::SSLAuthConn.new(host='localhost', port=LDAP_PORT, * start_tls=false, cert_path, cert_nickname, * key_password, sctrls=nil, cctrls=nil) * * => LDAP::SSLAuthConn * * Return a new LDAP::SSLConn connection to the server, +host+, on port +port+. * If +start_tls+ is *true*, START_TLS will be used to establish the * connection, automatically setting the LDAP protocol version to v3 if it is * not already set. * * +sctrls+ is an array of server controls, whilst +cctrls+ is an array of * client controls. * * Method accepts at least 6 parameters and an optional block. * */ void Init_ldap_clientauth() { rb_cLDAP_SSLAuthConn = rb_define_class_under(rb_mLDAP, "SSLAuthConn", rb_cLDAP_SSLConn); rb_define_singleton_method(rb_cLDAP_SSLAuthConn, "open", rb_ldap_sslauthconn_s_open, -1); rb_define_method(rb_cLDAP_SSLAuthConn, "initialize", rb_ldap_sslauthconn_initialize, -1); rb_define_method(rb_cLDAP_SSLAuthConn, "bind", rb_ldap_sslauthconn_s_bind, -1); } #endif ruby-ldap-0.9.16/mod.c0000644000004100000410000002041712260553634014473 0ustar www-datawww-data/* * mod.c * $Id: mod.c,v 1.14 2005/03/07 22:57:34 ianmacd Exp $ */ #include "ruby.h" #include "rbldap.h" VALUE rb_cLDAP_Mod; void rb_ldap_mod_free (RB_LDAPMOD_DATA * data) { if (data->mod) { struct berval **bvals; char **svals; int i; xfree(data->mod->mod_type); if (data->mod->mod_op & LDAP_MOD_BVALUES) { bvals = data->mod->mod_vals.modv_bvals; for (i = 0; bvals[i] != NULL; i++) { xfree (bvals[i]); } xfree (bvals); } else { svals = data->mod->mod_vals.modv_strvals; for (i = 0; svals[i] != NULL; i++) { xfree (svals[i]); } xfree (svals); } xfree (data->mod); } xfree (data); } static LDAPMod * rb_ldap_new_mod (int mod_op, char *mod_type, char **modv_strvals) { LDAPMod *mod; if (mod_op & LDAP_MOD_BVALUES) { rb_bug ("rb_ldap_mod_new: illegal mod_op"); } mod = ALLOC_N (LDAPMod, 1); mod->mod_op = mod_op; mod->mod_type = ALLOC_N(char,strlen(mod_type) + 1); strcpy(mod->mod_type, mod_type); mod->mod_vals.modv_strvals = modv_strvals; return mod; } VALUE rb_ldap_mod_new (int mod_op, char *mod_type, char **modv_strvals) { VALUE obj; RB_LDAPMOD_DATA *moddata; obj = Data_Make_Struct (rb_cLDAP_Mod, RB_LDAPMOD_DATA, 0, rb_ldap_mod_free, moddata); moddata->mod = rb_ldap_new_mod (mod_op, mod_type, modv_strvals); return obj; } static LDAPMod * rb_ldap_new_mod2 (int mod_op, char *mod_type, struct berval **modv_bvals) { LDAPMod *mod; if (!(mod_op & LDAP_MOD_BVALUES)) { rb_bug ("rb_ldap_mod_new: illegal mod_op"); } mod = ALLOC_N (LDAPMod, 1); mod->mod_op = mod_op; mod->mod_type = ALLOC_N(char,strlen(mod_type) + 1); strcpy(mod->mod_type, mod_type); mod->mod_vals.modv_bvals = modv_bvals; return mod; } VALUE rb_ldap_mod_new2 (int mod_op, char *mod_type, struct berval ** modv_bvals) { VALUE obj; RB_LDAPMOD_DATA *moddata; obj = Data_Make_Struct (rb_cLDAP_Mod, RB_LDAPMOD_DATA, 0, rb_ldap_mod_free, moddata); moddata->mod = rb_ldap_new_mod2 (mod_op, mod_type, modv_bvals); return obj; } static VALUE rb_ldap_mod_s_allocate (VALUE klass) { RB_LDAPMOD_DATA *moddata; VALUE obj; obj = Data_Make_Struct (klass, RB_LDAPMOD_DATA, 0, rb_ldap_mod_free, moddata); moddata->mod = NULL; return obj; } /* * call-seq: * Mod.new(mod_type, attr, vals) => LDAP::Mod * * Create a new LDAP::Mod object of type +mod_type+. This is most commonly * *LDAP_MOD_ADD*, *LDAP_MOD_REPLACE* or *LDAP_MOD_DELETE*, although some LDAP * servers may offer extension types. * * +attr+ should be the name of the attribute on which to operate, whilst * +vals+ is an array of values pertaining to +attr+. If +vals+ contains * binary data, +mod_type+ should be logically OR'ed (|) with * *LDAP_MOD_BVALUES*. * * LDAP::Mod objects can be passed to methods in the LDAP::Conn class, such as * Conn#add, Conn#add_ext, Conn#modify and Conn#modify_ext. */ static VALUE rb_ldap_mod_initialize (int argc, VALUE argv[], VALUE self) { struct berval **bvals; char **strvals; int mod_op; char *mod_type; int i; VALUE op, type, vals; RB_LDAPMOD_DATA *moddata; rb_scan_args (argc, argv, "3", &op, &type, &vals); Data_Get_Struct (self, RB_LDAPMOD_DATA, moddata); if (moddata->mod) return Qnil; mod_op = NUM2INT (op); mod_type = RSTRING_PTR(type); Check_Type (vals, T_ARRAY); if (mod_op & LDAP_MOD_BVALUES) { bvals = ALLOC_N (struct berval *, RARRAY_LEN (vals) + 1); for (i = 0; i < RARRAY_LEN (vals); i++) { VALUE str; struct berval *bval; str = RARRAY_PTR (vals)[i]; Check_Type (str, T_STRING); bval = ALLOC_N (struct berval, 1); bval->bv_len = RSTRING_LEN (str); RB_LDAP_SET_STR (bval->bv_val, str); bvals[i] = bval; } bvals[i] = NULL; moddata->mod = rb_ldap_new_mod2 (mod_op, mod_type, bvals); } else { strvals = ALLOC_N (char *, RARRAY_LEN (vals) + 1); for (i = 0; i < RARRAY_LEN (vals); i++) { VALUE str; char *sval; str = RARRAY_PTR (vals)[i]; RB_LDAP_SET_STR (sval, str); strvals[i] = sval; } strvals[i] = NULL; moddata->mod = rb_ldap_new_mod (mod_op, mod_type, strvals); } return Qnil; } /* * call-seq: * mod.mod_op => Fixnum * * Return the type of modification associated with the LDAP::Mod object. * Standard types are *LDAP_MOD_ADD*, *LDAP_MOD_REPLACE* and * *LDAP_MOD_DELETE*, although any of these may be logically OR'ed with * *LDAP_MOD_BVALUES* to indicate that the values of the Mod object contain * binary data. */ VALUE rb_ldap_mod_op (VALUE self) { RB_LDAPMOD_DATA *moddata; GET_LDAPMOD_DATA (self, moddata); return INT2NUM (moddata->mod->mod_op); } /* * call-seq: * mod.mod_type => String * * Return the name of the attribute associated with the LDAP::Mod object. */ VALUE rb_ldap_mod_type (VALUE self) { RB_LDAPMOD_DATA *moddata; GET_LDAPMOD_DATA (self, moddata); return rb_tainted_str_new2 (moddata->mod->mod_type); } /* * call-seq: * mod.mod_vals => Array of String * * Return the values associated with the Mod object. */ VALUE rb_ldap_mod_vals (VALUE self) { RB_LDAPMOD_DATA *moddata; struct berval **bvals; char **svals; int i; VALUE val; GET_LDAPMOD_DATA (self, moddata); if (moddata->mod->mod_op & LDAP_MOD_BVALUES) { bvals = moddata->mod->mod_vals.modv_bvals; val = rb_ary_new (); for (i = 0; bvals[i] != NULL; i++) { VALUE str; str = rb_tainted_str_new (bvals[i]->bv_val, bvals[i]->bv_len); rb_ary_push (val, str); } } else { svals = moddata->mod->mod_vals.modv_strvals; val = rb_ary_new (); for (i = 0; svals[i] != NULL; i++) { VALUE str; str = rb_tainted_str_new2 (svals[i]); rb_ary_push (val, str); } } return val; } /* call-seq: * mod.inspect => String * * Produce a concise representation of the Mod object. */ VALUE rb_ldap_mod_inspect (VALUE self) { VALUE str; VALUE hash = rb_hash_new (); const char *c; c = rb_obj_classname (self); str = rb_str_new (0, strlen (c) + 10 + 16 + 1); /* 10:tags 16:addr 1:nul */ sprintf (RSTRING_PTR (str), "#<%s:0x%lx ", c, self); #if RUBY_VERSION_CODE < 190 RSTRING(str)->len = strlen (RSTRING_PTR (str)); #else rb_str_set_len(str, strlen (RSTRING_PTR (str))); #endif switch (FIX2INT (rb_ldap_mod_op (self)) & ~LDAP_MOD_BVALUES) { case LDAP_MOD_ADD: rb_str_cat2 (str, "LDAP_MOD_ADD"); break; case LDAP_MOD_DELETE: rb_str_cat2 (str, "LDAP_MOD_DELETE"); break; case LDAP_MOD_REPLACE: rb_str_cat2 (str, "LDAP_MOD_REPLACE"); break; #ifdef LDAP_MOD_INCREMENT case LDAP_MOD_INCREMENT: rb_str_cat2 (str, "LDAP_MOD_INCREMENT"); break; #endif #ifdef LDAP_MOD_OP case LDAP_MOD_OP: rb_str_cat2 (str, "LDAP_MOD_OP"); break; #endif default: /* We shouldn't end up here. */ rb_str_cat2 (str, "unknown"); break; } if (FIX2INT (rb_ldap_mod_op (self)) & LDAP_MOD_BVALUES) rb_str_cat2 (str, "|LDAP_MOD_BVALUES"); rb_str_cat2 (str, "\n"); rb_hash_aset (hash, rb_ldap_mod_type (self), rb_ldap_mod_vals (self)); rb_str_concat (str, rb_inspect (hash)); rb_str_cat2 (str, ">"); return str; } /* Document-class: LDAP::Mod * * Create and manipulate LDAP::Mod objects, which can then be passed to methods * in the LDAP::Conn class, such as Conn#add, Conn#add_ext, Conn#modify and * Conn#modify_ext. */ void Init_ldap_mod () { rb_cLDAP_Mod = rb_define_class_under (rb_mLDAP, "Mod", rb_cObject); #if RUBY_VERSION_CODE < 170 rb_define_singleton_method (rb_cLDAP_Mod, "new", rb_ldap_class_new, -1); #endif #if RUBY_VERSION_CODE >= 173 rb_define_alloc_func (rb_cLDAP_Mod, rb_ldap_mod_s_allocate); #else rb_define_singleton_method (rb_cLDAP_Mod, "allocate", rb_ldap_mod_s_allocate, 0); #endif rb_ldap_mod_define_method ("initialize", rb_ldap_mod_initialize, -1); rb_ldap_mod_define_method ("mod_op", rb_ldap_mod_op, 0); rb_ldap_mod_define_method ("mod_type", rb_ldap_mod_type, 0); rb_ldap_mod_define_method ("mod_vals", rb_ldap_mod_vals, 0); rb_ldap_mod_define_method ("inspect", rb_ldap_mod_inspect, 0); /* rb_ldap_mod_define_method("mod_op=", rb_ldap_mod_set_op, 1); rb_ldap_mod_define_method("mod_type=", rb_ldap_mod_set_type, 1); rb_ldap_mod_define_method("mod_vals=", rb_ldap_mod_set_vals, 1); */ } ruby-ldap-0.9.16/extconf.rb0000755000004100000410000002147612260553634015554 0ustar www-datawww-data#!/usr/bin/env ruby # # extconf.rb for ldap extension # $Id: extconf.rb,v 1.7 2006/04/18 23:49:56 ianmacd Exp $ # require 'mkmf' $INTERACTIVE = false if( ARGV.include?("--help") ) print <= 6.0 nspr >= 4.0'} if $? == 0 puts 'Mozzilla LDAP libs will be used.' $mozlibs = %x{pkg-config mozldap nspr --libs}.chomp $mozincs = %x{pkg-config mozldap nspr --cflags}.chomp else puts 'pkg-config reported that no right mozilla LDAP libs were found' puts 'we need mozldap >= 6.0 and nspr >= 4.0' exit 1 end $defs << "-DUSE_NETSCAPE_SDK -DUSE_SSL_CLIENTAUTH" #$libnsl = ldap_with_config("libnsl", "nsl") #$libpthread = ldap_with_config("libpthread", "pthread") $libresolv = ldap_with_config("libresolv", "resolv") $libldap = ldap_with_config("libldap", "ldap60") $libns = ldap_with_config("libns", "nspr4,plc4,plds4").split(",") $liblber = ldap_with_config("liblber", "lber60") $libssl = ldap_with_config("libssl", "ssl3") end end if( $use_openldap1 ) $defs << "-DUSE_OPENLDAP1" $defs << "-DUSE_OPENLDAP" $libresolv = ldap_with_config("libresolv", "resolv") $libldap = ldap_with_config("libldap", "ldap") $liblber = ldap_with_config("liblber", "lber") end if( $use_openldap2 ) $defs << "-DUSE_OPENLDAP2" $defs << "-DUSE_OPENLDAP" # OpenLDAP 2.3 finally deprecates a bunch of non-_ext functions. We need # this to enable them. $defs << "-DLDAP_DEPRECATED" $libresolv = ldap_with_config("libresolv", "resolv") $libcrypto = ldap_with_config("libcrypto", "crypto") $libssl = ldap_with_config("libssl", "ssl") $libpthread = ldap_with_config("libpthread", "pthread") $libnsl = ldap_with_config("libnsl", "nsl") $liblber = ldap_with_config("liblber", "lber") $libldap_r = ldap_with_config("libldap_r", "ldap_r") $libldap = ldap_with_config("libldap", "ldap") end if( $use_wldap32 ) srcdir = File.dirname($0) if( !File.exist?("win") ) Dir.mkdir("win") end `lib /def:#{srcdir}/win/wldap32.def /out:#{srcdir}/win/wldap32.lib` $defs << "-DUSE_WLDAP32" dir_config("wldap32", "#{srcdir}/win", "./win") $libldap = ldap_with_config("libldap", "wldap32") end if( $libpthread ) $defs << "-D_REENTRANT" end if( $use_wldap32 ) have_header("winldap.h") have_header("winlber.h") have_header("sys/time.h") elsif $use_netscape =~ /^6/ # mozilla pkg_config('mozldap') pkg_config('nspr') else ldap_h = have_header("ldap.h") lber_h = have_header("lber.h") ldap_ssl_h = have_header("ldap_ssl.h") if( !(ldap_h && lber_h) ) print("can't find ldap.h and lber.h\n") print("use the option '--with-ldap-dir'!\n") exit(0) end have_header("openssl/ssl.h") || have_header("ssl.h") have_header("openssl/crypto.h") || have_header("crypto.h") end $LIBS << ' -pthread' for l in [$libcrypto, $libssl, $libnsl, $libpthread, $libresolv, $libns, $liblber, $libldap_r, $libldap].flatten if( l ) have_library(l) end end have_func("ldap_init", 'ldap.h') have_func("ldap_set_option") have_func("ldap_get_option") have_func("ldap_start_tls_s") if $use_openldap2 have_func("ldap_memfree") have_func("ldap_perror") if !arg_config("--disable-ldap-perror") have_func("ldap_sort_entries") #have_func("ldap_sort_values") have_func("ldapssl_init") # NS SDK have_func("ldap_sslinit") # WLDAP32 have_func("ldap_sasl_bind_s") have_func("ldap_rename_s") have_func("ldap_compare_s") have_func("ldap_add_ext_s") have_func("ldap_compare_ext_s") have_func("ldap_delete_ext_s") have_func("ldap_modify_ext_s") have_func("ldap_search_ext_s") have_func("ldap_unbind_ext_s") have_func("ldap_sasl_interactive_bind_s") $defs << "-DRUBY_VERSION_CODE=#{RUBY_VERSION.gsub(/\D/, '')}" create_makefile("ldap") $slapd = ldap_with_config("slapd") || File.join($ldap_dir,"libexec","slapd") $schema_dir = ldap_with_config("schema-dir") if( !$schema_dir ) $schema_dir = File.join($ldap_dir,"etc","openldap","schema") if( !File.exist?($schema_dir) ) $schema_dir = File.join($ldap_dir,"etc","openldap") end end $run_test = "/bin/sh $(srcdir)/test/test.sh #{CONFIG['RUBY_INSTALL_NAME']}" if( $use_openldap1 ) $run_test += " openldap1" else( $use_openldap2 ) if( $libssl && $libcrypto ) $run_test = "/bin/sh $(srcdir)/test/test.sh #{CONFIG['RUBY_INSTALL_NAME']} newcert; " + $run_test $run_test += " openldap2-ssl" else $run_test += " openldap2" end end $run_test += " #{$slapd} #{$schema_dir}" File.open("Makefile","a") do |f| f.print < [ 'top', 'person' ] #, ... } conn.add( "cn=foobar, dc=localhost, dc=localdomain", entry ) Q. Can I use SASL authentication? A. Yes, it works for me using Cyrus SASL and Kerberos V via GSSAPI. Use LDAP::Conn#sasl_bind. Your mileage may vary. Q. Can I put a limit on the number of results returned by the server? A. Yes, as of version 0.9.4, you can. Set the size limit using LDAP::Conn#set_option and then check for LDAP::Conn#search or LDAP::Conn#search2 having exceeded this limit, by using LDAP::Conn#err: conn = LDAP::Conn.new( 'localhost', 389 ) # Limit the results set to a maximum of 10. conn.set_option( LDAP::LDAP_OPT_SIZELIMIT, 10 ) conn.search2( 'dc=localhost,dc=localdomain', LDAP::LDAP_SCOPE_SUBTREE, '(objectClass=*)' ) if conn.err == LDAP::LDAP_SIZELIMIT_EXCEEDED # Results set was truncated by server. end Note that LDAP::LDAP_SIZELIMIT_EXCEEDED may occur even when you have not put an explicit limit on the number of results to be returned. The server will likely have its own maximum configured, so it can be important to check for this condition on all of your calls to LDAP::Conn#search and LDAP::Conn#search2. ruby-ldap-0.9.16/README0000644000004100000410000002462112260553634014431 0ustar www-datawww-data Ruby/LDAP -- A Ruby extension library for LDAP Copyright (C) 2000-2004 Takaaki Tateishi Copyright (C) 2005-2006 Ian Macdonald Copyright (C) 2009 Alexey Chebotar ------------------------------------------------------------------------------- DESCRIPTION Ruby/LDAP is a Ruby extension library that provides an interface to the LDAP API as described in RFC1823. ------------------------------------------------------------------------------- REQUIREMENT * Ruby 1.8.x or 1.9.x * OpenLDAP, Netscape SDK, Windows 2003 or Windows XP ------------------------------------------------------------------------------- PORTS * FreeBSD ("Akinori -Aki- MUSHA" ) * Debian (Akira Yamada ) ------------------------------------------------------------------------------- BUILDING extconf.rb will try to use the OpenLDAP 2 or Netscape SDK libraries and guess paths to some header files and libraries from the position of ldap.h. If you'd like to see the available options for extconf.rb, run it with '--help' option. $ ruby extconf.rb [--with-openldap1|--with-openldap2|--with-netscape|--with-wldap32] $ make This will create ldap.so, which you can either manually copy into place or install with: $ make install If you're building the software on Windows, you may need to use nmake instead of make. ------------------------------------------------------------------------------- LICENSE See COPYING. ------------------------------------------------------------------------------- AVAILABLE CLASSES and METHODS LDAP::LDAP_VERSION LDAP::LDAP_MAX_VERSION LDAP::VERSION LDAP::MAJOR_VERSION LDAP::MINOR_VERSION LDAP::LDAP_PORT LDAP::LDAPS_PORT LDAP::LDAP_API_INFO_VERSION LDAP::LDAP_VENDOR_NAME LDAP::LDAP_VENDOR_VERSION LDAP::LDAP_API_VERSION LDAP.err2string(errcode) LDAP.dn2ufn(dn) LDAP.mod(mod_op, mod_type, mod_vals) (= LDAP::Mod.new) LDAP.hash2mods(mod_op, hash) LDAP.entry2hash(entry) (= entry.to_hash) LDAP::Conn.new(host = "localhost", port = LDAP::LDAP_PORT) : conn (raise LDAP::Error) LDAP::Conn.open(host = "localhost", port = LDAP::LDAP_PORT) : conn (raise LDAP::Error) LDAP::Conn#simple_bind(dn = nil, password = nil) { ... } : conn (raise LDAP::ResultError) LDAP::Conn#bind(dn = nil, password = nil, method = LDAP::LDAP_AUTH_SIMPLE) {|conn| ... } (raise LDAP::ResultError) LDAP::Conn#bind(dn = nil, password = nil, method = LDAP::LDAP_AUTH_SIMPLE) : conn (raise LDAP::ResultError) LDAP::Conn#sasl_bind(dn = nil, mech = nil, cred = nil, sctrls=nil, cctrls=nil) {|conn| ... } (raise LDAP::ResultError) LDAP::Conn#sasl_bind(dn = nil, mech = nil, cred = nil, sctrls=nil, cctrls=nil) : conn (raise LDAP::ResultError) LDAP::Conn#bound? : true || false LDAP::Conn#unbind() (raise LDAP::ResultError) LDAP::Conn#start_tls LDAP::Conn#perror(str) LDAP::Conn#result2error(ldap_msg) : errcode LDAP::Conn#err2string(errcode) : errmsg LDAP::Conn#get_errno : errcode [if available] LDAP::Conn#search(basedn, scope, filter, attrs = nil, attrsonly = false, sec = 0, usec = 0, s_attr = nil, s_proc = nil) {|entry| ... } : conn (raise LDAP::ResultError) LDAP::Conn#search2(basedn, scope, filter, attrs = nil, attrsonly = false, sec = 0, usec = 0, s_attr = nil, s_proc = nil) {|entry_as_hash| ... } : conn (if a block is given) / Array of Hash (if no block is given) (raise LDAP::ResultError) LDAP::Conn#search_ext(basedn, scope, filter, attrs = nil, attrsonly = false, serverctrls, clientctrls, sec = 0, usec = 0, s_attr = nil, s_proc = nil) {|entry| ... } : conn (raise LDAP::ResultError) LDAP::Conn#search_ext2(basedn, scope, filter, attrs = nil, attrsonly = false, serverctrls, clientctrls, sec = 0, usec = 0, s_attr = nil, s_proc = nil) {|entry_as_hash| ... } : conn (if a block is given) / Array of Hash (if no block is given) (raise LDAP::ResultError) LDAP::Conn#add(dn, ldap_mods) : self (raise LDAP::ResultError) LDAP::Conn#add_ext(dn, ldap_mods, serverctrls, clientctrls) : self (raise LDAP::ResultError) LDAP::Conn#modify(dn, ldap_mods) : self (raise LDAP::ResultError) LDAP::Conn#modify_ext(dn, ldap_mods, serverctrls, clientctrls) : self (raise LDAP::ResultError) LDAP::Conn#modrdn(olddn, newdn, delete) : self (raise LDAP::ResultError) LDAP::Conn#delete(dn) : self (raise LDAP::ResultError) LDAP::Conn#delete(dn, serverctrls, clientctrls) : self (raise LDAP::ResultError) LDAP::Conn#compare(dn, attr, val) : self LDAP::Conn#compare_ext(dn, attr, val, serverctrls, clientctrls) : self LDAP::Conn#set_option(opt, data) : self (raise LDAP::ResultError) LDAP::Conn#get_option(opt) : data (raise LDAP::ResultError) LDAP::Conn#schema(base = nil, attrs = nil, sec = 0, usec = 0) : LDAP::Schema LDAP::Conn#root_dse(attrs = nil, sec = 0, usec = 0) : Array of Hash LDAP::SSLConn.new(host = 'localhost', port = LDAP_PORT, start_tls = false, sctrls=nil, cctrls=nil) : conn (raise LDAP::Error) LDAP::Mod.new(mod_op, mod_type, mod_vals) : ldap_mod LDAP::Mod#inspect : String LDAP::Mod#mod_op : mod_op LDAP::Mod#mod_type : mod_type LDAP::Mod#mod_vals : mod_vals LDAP::Mod#mod_op=(mod_op) LDAP::Mod#mod_type=(mod_type) LDAP::Mod#mod_vals=(mod_vals) LDAP::Entry#get_dn : dn LDAP::Entry#get_values : vals LDAP::Entry#get_attributes : attrs LDAP::Entry#dn (= get_dn) LDAP::Entry#vals (= get_values) LDAP::Entry#[] (= get_values) LDAP::Entry#attrs (= get_attributes) LDAP::Entry#to_hash : Hash LDAP::Entry#inspect : String LDAP::Control.new : LDAP::Control LDAP::Control#oid : String LDAP::Control#oid=(oid) : oid LDAP::Control#critical : true || false LDAP::Control#critical? : true || false LDAP::Control#critical=(crit) : crit LDAP::Control#value : String LDAP::Control#value=(val) : val LDAP::Control#inspect : String SSLConn is a subclass of Conn, so its objects have access to the same methods as Conn objects. In ldap/schema.rb: LDAP::Conn#schema(attrs = nil, sec = 0, usec = 0) : schema LDAP::Schema#must(oc) : attributes LDAP::Schema#may(oc) : attributes LDAP::Schema#names(attr) : names LDAP::Schema#sup(oc) : object class In ldap/control.rb: LDAP::Control.encode(array) : String LDAP::Control#decode : Array In ldap/ldif.rb: LDAP::Entry#to_ldif : LDAP::LDIF::Entry LDAP::Entry#to_s : Alias of LDAP::Entry#to_ldif LDAP::Mod#to_ldif(dn) : LDAP::LDIF::Mod LDAP::Mod#to_s(dn) : Alias of LDAP::Mod#to_ldif LDAP::Record.new(dn, change_type, attrs, mods=nil, ctrls=nil) LDAP::Record#send(conn) : self LDAP::Record#clean : self LDAP::LDIF.mods_to_ldif( dn, *mods ) LDAP::LDIF.parse_entry(lines) : LDAP::Record (raise LDAP::LDIFError) LDAP::LDIF.parse_file(file, sort=false) : self (if a block is given) / Array (if no block is given) See also test/*.rb for examples. ------------------------------------------------------------------------------- REFERENCES * T. Howes, M. Smith (University of Michigan): RFC1823, The LDAP Application Program Interface, August 1995 * T. Howes (University of Michigan): RFC1960, A String Representation of LDAP Search Filters, June 1996 * M. Wahl, Critical Angle Inc, T. Hows, Netscape Communications Gorp., S. Kille, Isode Limited: Lightweight Directory Access Protocol (v3), December 1997 * M. Wahl, Critical Angle Inc., A. Coulbeck, Isode Inc., T. Howes, Netscape Communications Corp., S. Kille, Isode Limited: December 1997 * M .Wahl, Critical Angle Inc., S. Kille, Isode Ltd., T. Howes, Netscape Communications Corp.: Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names, December 1997 * T. Howes, Netscape Communications Gorp.: The String Representation of LDAP Search Filters, December 1997 * F. Yergeau (Alis Technologies): RFC2279, UTF-8, a transformation format of ISO 10646, October 1998 * Netscape Communications Corp.: Netscape Directory SDK * C. Weider, A. Herron, A. Anantha, T. Howes: RFC2696, LDAP Control Extension for Simple Paged Results Manipulation, September 1999 * Luiz Ernesto Pinheiro Malere: LDAP Linux HOWTO, February 2000 * G. Good: RFC2849, The LDAP Data Interchange Format (LDIF) - Technical Specification, June 2000. * Tim Howes, Mark Smith: Understanding and Deploying LDAP Directory Servers * The OpenLDAP Project: OpenLDAP 2.2 Administrator's Guide, February 2004 Here are some URLs that contain useful information about LDAP: * University of Michigan http://www.umich.edu/~dirsvcs/ldap/ * OpenLDAP Project http://www.openldap.org/ * Netscape Communications http://developer.netscape.com/docs/manuals/communicator/ldap45.htm * Netscape Directory SDK http://www.mozilla.org/directory/ * Active Directory Service Interfaces Overview http://www.microsoft.com/windows2000/techinfo/howitworks/activedirectory/ adsilinks.asp * LDAP schema repository http://www.hklc.com/ldapschema/ http://ldap.hklc.com/ * Object Identifiers Registry http://www.alvestrand.no/harald/objectid/ ------------------------------------------------------------------------------- THANKS This list maybe not correct. If you notice mistakes of this list, please point out. * Adam Doligalski * Akinori MUSHA * Akira Yamada * Andrew Broman * Anthony M. Martinez * Antonio Terceiro * Aprotim Sanyal * Brian Leake * Chris Scharf * David Campbell * Francesco Malvezzi * Hadmut Danisch * Hiroki Najima * Jan Mikkelsen * Kouhei Sutou * Marek Veber * Mark Kittisopikul * Michael Granger * Milos Jakubicek * Pirmin Kalberer * Radek Hnilica * S. Potter * Tilo Sloboda * Usa Nakamura * Yuri Arabadji * Yuuzou Gotou * atsu@@metallic.co.jp * bbense * bidon ruby-ldap-0.9.16/ldap.c0000644000004100000410000004275112260553634014641 0ustar www-datawww-data/* -*- C -*- * * ldap.c * $Id: ldap.c,v 1.14 2005/03/15 10:07:48 ianmacd Exp $ */ #include "ruby.h" #include "rbldap.h" VALUE rb_mLDAP; VALUE rb_eLDAP_Error; VALUE rb_eLDAP_ResultError; VALUE rb_eLDAP_InvalidDataError; VALUE rb_eLDAP_InvalidEntryError; VALUE rb_ldap_class_new (int argc, VALUE argv[], VALUE klass) { VALUE obj; obj = rb_funcall (klass, rb_intern ("allocate"), 0); rb_obj_call_init (obj, argc, argv); return obj; } VALUE rb_ldap_dummy_method (int argc, VALUE argv[], VALUE self) { /* do nothing */ return Qnil; } /* * call-seq: * LDAP.err2string(err) => String * * Return the text string associated with the LDAP error, +err+. */ VALUE rb_ldap_err2string (VALUE self, VALUE err) { char *cmsg; VALUE msg; cmsg = ldap_err2string (NUM2INT (err)); msg = rb_tainted_str_new2 (cmsg); return msg; } /* * call-seq: * LDAP.dn2ufn(dn) => String or nil * * Translate the DN, +dn+, to a more User-Friendly Name (UFN). * * For example: * * LDAP.dn2ufn('uid=ianmacd,ou=People,dc=google,dc=com') * * produces: * * ianmacd, People, google.com * * The UFN format is described in * RFC1781[http://www.faqs.org/rfcs/rfc1781.html]. */ VALUE rb_ldap_dn2ufn (VALUE self, VALUE dn) { char *c_dn; char *c_ufn; if (dn == Qnil) { return Qnil; } c_dn = StringValueCStr (dn); if ((c_ufn = ldap_dn2ufn (c_dn))) { return rb_tainted_str_new2 (c_ufn); } else { return Qnil; } } VALUE rb_ldap_explode_dn (VALUE self, VALUE dn, VALUE notypes) { char **c_arr, **p; char *c_dn; VALUE ary; if (dn == Qnil) { return Qnil; } c_dn = StringValueCStr (dn); if ((c_arr = ldap_explode_dn (c_dn, RTEST (notypes) ? 1 : 0))) { ary = rb_ary_new (); for (p = c_arr; *p != NULL; p++) { rb_ary_push (ary, rb_tainted_str_new2 (*p)); } ldap_value_free (c_arr); return ary; } else { return Qnil; } } VALUE rb_ldap_explode_rdn (VALUE self, VALUE rdn, VALUE notypes) { char **c_arr, **p; char *c_dn; VALUE ary; if (rdn == Qnil) { return Qnil; } c_dn = StringValueCStr (rdn); if ((c_arr = ldap_explode_rdn (c_dn, RTEST (notypes) ? 1 : 0))) { ary = rb_ary_new (); for (p = c_arr; *p != NULL; p++) { rb_ary_push (ary, rb_tainted_str_new2 (*p)); } ldap_value_free (c_arr); return ary; } else { return Qnil; } } /* * call-seq: * LDAP.mod(mod_type, attr, vals) => LDAP::Mod * * Create a new LDAP::Mod object of type, +mod_type+. This is most commonly * *LDAP_MOD_ADD*, *LDAP_MOD_REPLACE* or *LDAP_MOD_DELETE*, although some LDAP * servers may offer extension types. * * +attr+ should be the name of the attribute on which to operate, whilst * +vals+ is an array of values pertaining to +attr+. If +vals+ contains * binary data, +mod_type+ should be logically OR'ed (|) with * *LDAP_MOD_BVALUES*. * * LDAP::Mod objects can be passed to methods in the LDAP::Conn class, such as * Conn#add, Conn#add_ext, Conn#modify and Conn#modify_ext. */ static VALUE rb_ldap_mod_s_new (int argc, VALUE argv[], VALUE klass) { return rb_ldap_class_new (argc, argv, rb_cLDAP_Mod); } static VALUE rb_ldap_hash2mods_i (VALUE type_vals, VALUE tmp) { VALUE type, vals, op, result; VALUE args[3]; op = rb_ary_entry (tmp, 0); result = rb_ary_entry (tmp, 1); type = rb_ary_entry (type_vals, 0); vals = rb_ary_entry (type_vals, 1); args[0] = op, args[1] = type, args[2] = vals; rb_ary_push (result, rb_ldap_mod_s_new (3, args, rb_cLDAP_Mod)); return Qnil; } /* * call-seq: * LDAP.hash2mods(mod_type, hash) => Array of LDAP::Mod * * Convert a hash into an array of LDAP::Mod objects. +mod_type+ should * contain the mod type, which is most commonly *LDAP_MOD_ADD*, * *LDAP_MOD_REPLACE* or *LDAP_MOD_DELETE*, although some LDAP servers may * offer extension types. */ VALUE rb_ldap_hash2mods (VALUE self, VALUE op, VALUE hash) { VALUE tmp; tmp = rb_assoc_new (op, rb_ary_new ()); rb_iterate (rb_each, hash, rb_ldap_hash2mods_i, tmp); return rb_ary_entry (tmp, 1); } /* * call-seq: * LDAP.entry2hash(entry) => Hash * * Convert the entry, +entry+, to a hash. */ VALUE rb_ldap_entry2hash (VALUE self, VALUE entry) { return rb_ldap_entry_to_hash (entry); } extern void Init_ldap_entry (); extern void Init_ldap_conn (); extern void Init_ldap_sslconn (); extern void Init_ldap_saslconn (); #ifdef USE_SSL_CLIENTAUTH extern void Init_ldap_clientauth (); #endif extern void Init_ldap_mod (); extern void Init_ldap_misc (); /* Document-class: LDAP * * Container module for LDAP-related classes. */ void Init_ldap () { rb_mLDAP = rb_define_module ("LDAP"); rb_define_const (rb_mLDAP, "LDAP_VERSION", INT2NUM (LDAP_VERSION)); #ifdef LDAP_VERSION1 rb_define_const (rb_mLDAP, "LDAP_VERSION1", INT2NUM (LDAP_VERSION1)); #endif #ifdef LDAP_VERSION2 rb_define_const (rb_mLDAP, "LDAP_VERSION2", INT2NUM (LDAP_VERSION2)); #endif #ifdef LDAP_VERSION3 rb_define_const (rb_mLDAP, "LDAP_VERSION3", INT2NUM (LDAP_VERSION3)); #endif #ifdef LDAP_VERSION_MAX rb_define_const (rb_mLDAP, "LDAP_VERSION_MAX", INT2NUM (LDAP_VERSION_MAX)); #else rb_define_const (rb_mLDAP, "LDAP_VERSION_MAX", INT2NUM (LDAP_VERSION)); #endif rb_define_const (rb_mLDAP, "VERSION", rb_tainted_str_new2 (RB_LDAP_VERSION)); rb_define_const (rb_mLDAP, "MAJOR_VERSION", INT2NUM (RB_LDAP_MAJOR_VERSION)); rb_define_const (rb_mLDAP, "MINOR_VERSION", INT2NUM (RB_LDAP_MINOR_VERSION)); rb_define_const (rb_mLDAP, "PATCH_VERSION", INT2NUM (RB_LDAP_PATCH_VERSION)); #ifdef LDAP_API_INFO_VERSION rb_define_const (rb_mLDAP, "LDAP_API_INFO_VERSION", INT2NUM (LDAP_API_INFO_VERSION)); #else rb_define_const (rb_mLDAP, "LDAP_API_INFO_VERSION", Qnil); #endif #ifdef LDAP_VENDOR_VERSION rb_define_const (rb_mLDAP, "LDAP_VENDOR_VERSION", INT2NUM (LDAP_VENDOR_VERSION)); #else rb_define_const (rb_mLDAP, "LDAP_VENDOR_VERSION", Qnil); #endif #ifdef LDAP_VENDOR_NAME rb_define_const (rb_mLDAP, "LDAP_VENDOR_NAME", rb_tainted_str_new2 (LDAP_VENDOR_NAME)); #else rb_define_const (rb_mLDAP, "LDAP_VENDOR_NAME", Qnil); #endif #ifdef LDAP_API_VERSION rb_define_const (rb_mLDAP, "LDAP_API_VERSION", INT2NUM (LDAP_API_VERSION)); #else rb_define_const (rb_mLDAP, "LDAP_API_VERSION", Qnil); #endif rb_define_const (rb_mLDAP, "LDAP_PORT", INT2NUM (389)); rb_define_const (rb_mLDAP, "LDAPS_PORT", INT2NUM (636)); rb_eLDAP_Error = rb_define_class_under (rb_mLDAP, "Error", rb_eStandardError); rb_eLDAP_ResultError = rb_define_class_under (rb_mLDAP, "ResultError", rb_eLDAP_Error); rb_eLDAP_InvalidDataError = rb_define_class_under (rb_mLDAP, "InvalidDataError", rb_eLDAP_Error); rb_eLDAP_InvalidEntryError = rb_define_class_under (rb_mLDAP, "InvalidEntryError", rb_eLDAP_InvalidDataError); rb_define_module_function (rb_mLDAP, "err2string", rb_ldap_err2string, 1); rb_define_module_function (rb_mLDAP, "explode_dn", rb_ldap_explode_dn, 2); rb_define_module_function (rb_mLDAP, "explode_rdn", rb_ldap_explode_rdn, 2); rb_define_module_function (rb_mLDAP, "dn2ufn", rb_ldap_dn2ufn, 1); rb_define_module_function (rb_mLDAP, "mod", rb_ldap_mod_s_new, -1); rb_define_module_function (rb_mLDAP, "hash2mods", rb_ldap_hash2mods, 2); rb_define_module_function (rb_mLDAP, "entry2hash", rb_ldap_entry2hash, 1); /* the following error code must be defined in ldap.h */ #define rb_ldap_define_err_code(code) rb_define_const(rb_mLDAP,#code,INT2NUM(code)) rb_ldap_define_err_code (LDAP_SUCCESS); rb_ldap_define_err_code (LDAP_OPERATIONS_ERROR); rb_ldap_define_err_code (LDAP_PROTOCOL_ERROR); rb_ldap_define_err_code (LDAP_TIMELIMIT_EXCEEDED); rb_ldap_define_err_code (LDAP_SIZELIMIT_EXCEEDED); rb_ldap_define_err_code (LDAP_COMPARE_FALSE); rb_ldap_define_err_code (LDAP_COMPARE_TRUE); #ifdef LDAP_STRONG_AUTH_NOT_SUPPORTED rb_ldap_define_err_code (LDAP_STRONG_AUTH_NOT_SUPPORTED); #endif #ifdef LDAP_AUTH_METHOD_NOT_SUPPORTED rb_ldap_define_err_code (LDAP_AUTH_METHOD_NOT_SUPPORTED); #endif rb_ldap_define_err_code (LDAP_STRONG_AUTH_REQUIRED); #ifdef LDAP_REFERRAL rb_ldap_define_err_code (LDAP_REFERRAL); #endif #ifdef LDAP_ADMINLIMIT_EXCEEDED rb_ldap_define_err_code (LDAP_ADMINLIMIT_EXCEEDED); #endif #ifdef LDAP_UNAVAILABLE_CRITICAL_EXTENSION rb_ldap_define_err_code (LDAP_UNAVAILABLE_CRITICAL_EXTENSION); #endif #ifdef LDAP_CONFIDENTIALITY_REQUIRED rb_ldap_define_err_code (LDAP_CONFIDENTIALITY_REQUIRED); #endif #ifdef LDAP_SASL_BIND_IN_PROGRESS rb_ldap_define_err_code (LDAP_SASL_BIND_IN_PROGRESS); #endif #ifdef LDAP_PARTIAL_RESULTS rb_ldap_define_err_code (LDAP_PARTIAL_RESULTS); #endif rb_ldap_define_err_code (LDAP_NO_SUCH_ATTRIBUTE); rb_ldap_define_err_code (LDAP_UNDEFINED_TYPE); rb_ldap_define_err_code (LDAP_INAPPROPRIATE_MATCHING); rb_ldap_define_err_code (LDAP_CONSTRAINT_VIOLATION); rb_ldap_define_err_code (LDAP_TYPE_OR_VALUE_EXISTS); rb_ldap_define_err_code (LDAP_INVALID_SYNTAX); rb_ldap_define_err_code (LDAP_NO_SUCH_OBJECT); rb_ldap_define_err_code (LDAP_ALIAS_PROBLEM); rb_ldap_define_err_code (LDAP_INVALID_DN_SYNTAX); rb_ldap_define_err_code (LDAP_IS_LEAF); rb_ldap_define_err_code (LDAP_ALIAS_DEREF_PROBLEM); rb_ldap_define_err_code (LDAP_INAPPROPRIATE_AUTH); rb_ldap_define_err_code (LDAP_INVALID_CREDENTIALS); rb_ldap_define_err_code (LDAP_INSUFFICIENT_ACCESS); rb_ldap_define_err_code (LDAP_BUSY); rb_ldap_define_err_code (LDAP_UNAVAILABLE); rb_ldap_define_err_code (LDAP_UNWILLING_TO_PERFORM); rb_ldap_define_err_code (LDAP_LOOP_DETECT); rb_ldap_define_err_code (LDAP_NAMING_VIOLATION); rb_ldap_define_err_code (LDAP_OBJECT_CLASS_VIOLATION); rb_ldap_define_err_code (LDAP_NOT_ALLOWED_ON_NONLEAF); rb_ldap_define_err_code (LDAP_NOT_ALLOWED_ON_RDN); rb_ldap_define_err_code (LDAP_ALREADY_EXISTS); rb_ldap_define_err_code (LDAP_NO_OBJECT_CLASS_MODS); rb_ldap_define_err_code (LDAP_RESULTS_TOO_LARGE); rb_ldap_define_err_code (LDAP_OTHER); rb_ldap_define_err_code (LDAP_SERVER_DOWN); rb_ldap_define_err_code (LDAP_LOCAL_ERROR); rb_ldap_define_err_code (LDAP_ENCODING_ERROR); rb_ldap_define_err_code (LDAP_DECODING_ERROR); rb_ldap_define_err_code (LDAP_TIMEOUT); rb_ldap_define_err_code (LDAP_AUTH_UNKNOWN); rb_ldap_define_err_code (LDAP_FILTER_ERROR); rb_ldap_define_err_code (LDAP_USER_CANCELLED); rb_ldap_define_err_code (LDAP_PARAM_ERROR); rb_ldap_define_err_code (LDAP_NO_MEMORY); /* rb_ldap_define_err_code(LDAP_CONNECT_ERROR); */ #undef rb_ldap_define_err_code #define rb_ldap_define_opt(code) rb_define_const(rb_mLDAP,#code,INT2NUM((int)code)) #ifdef LDAP_OPT_ON rb_ldap_define_opt (LDAP_OPT_ON); #endif #ifdef LDAP_OPT_OFF rb_ldap_define_opt (LDAP_OPT_OFF); #endif #ifdef LDAP_OPT_DESC rb_ldap_define_opt (LDAP_OPT_DESC); #endif #ifdef LDAP_OPT_DEREF rb_ldap_define_opt (LDAP_OPT_DEREF); #endif #ifdef LDAP_OPT_SIZELIMIT rb_ldap_define_opt (LDAP_OPT_SIZELIMIT); #endif #ifdef LDAP_OPT_TIMELIMIT rb_ldap_define_opt (LDAP_OPT_TIMELIMIT); #endif #ifdef LDAP_OPT_NETWORK_TIMEOUT rb_ldap_define_opt (LDAP_OPT_NETWORK_TIMEOUT); #endif #ifdef LDAP_OPT_THREAD_FN_PTRS rb_ldap_define_opt (LDAP_OPT_THREAD_FN_PTRS); #endif #ifdef LDAP_OPT_REBIND_FN rb_ldap_define_opt (LDAP_OPT_REBIND_FN); #endif #ifdef LDAP_OPT_REBIND_ARG rb_ldap_define_opt (LDAP_OPT_REBIND_ARG); #endif #ifdef LDAP_OPT_REFERRALS rb_ldap_define_opt (LDAP_OPT_REFERRALS); #endif #ifdef LDAP_OPT_RESTART rb_ldap_define_opt (LDAP_OPT_RESTART); #endif #ifdef LDAP_OPT_SSL rb_ldap_define_opt (LDAP_OPT_SSL); #endif #ifdef LDAP_OPT_IO_FN_PTRS rb_ldap_define_opt (LDAP_OPT_IO_FN_PTRS); #endif #ifdef LDAP_OPT_CACHE_FN_PTRS rb_ldap_define_opt (LDAP_OPT_CACHE_FN_PTRS); #endif #ifdef LDAP_OPT_CACHE_STRATEGY rb_ldap_define_opt (LDAP_OPT_CACHE_STRATEGY); #endif #ifdef LDAP_OPT_CACHE_ENABLE rb_ldap_define_opt (LDAP_OPT_CACHE_ENABLE); #endif #ifdef LDAP_OPT_REFERRAL_HOP_LIMIT rb_ldap_define_opt (LDAP_OPT_REFERRAL_HOP_LIMIT); #endif #ifdef LDAP_OPT_PROTOCOL_VERSION rb_ldap_define_opt (LDAP_OPT_PROTOCOL_VERSION); #endif #ifdef LDAP_OPT_SERVER_CONTROLS rb_ldap_define_opt (LDAP_OPT_SERVER_CONTROLS); #endif #ifdef LDAP_OPT_CLIENT_CONTROLS rb_ldap_define_opt (LDAP_OPT_CLIENT_CONTROLS); #endif #ifdef LDAP_OPT_PREFERRED_LANGUAGE rb_ldap_define_opt (LDAP_OPT_PREFERRED_LANGUAGE); #endif #ifdef LDAP_OPT_API_INFO rb_ldap_define_opt (LDAP_OPT_API_INFO); #endif #ifdef LDAP_OPT_API_FEATURE_INFO rb_ldap_define_opt (LDAP_OPT_API_FEATURE_INFO); #endif #ifdef LDAP_OPT_HOST_NAME rb_ldap_define_opt (LDAP_OPT_HOST_NAME); #endif #ifdef USE_OPENLDAP2 /* OpenLDAP TLS,SASL options */ #ifdef LDAP_OPT_X_TLS_CACERTFILE rb_ldap_define_opt (LDAP_OPT_X_TLS_CACERTFILE); #endif #ifdef LDAP_OPT_X_TLS_CACERTDIR rb_ldap_define_opt (LDAP_OPT_X_TLS_CACERTDIR); #endif #ifdef LDAP_OPT_X_TLS_CERT rb_ldap_define_opt (LDAP_OPT_X_TLS_CERT); #endif #ifdef LDAP_OPT_X_TLS_CERTFILE rb_ldap_define_opt (LDAP_OPT_X_TLS_CERTFILE); #endif #ifdef LDAP_OPT_X_TLS_KEYFILE rb_ldap_define_opt (LDAP_OPT_X_TLS_KEYFILE); #endif #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT rb_ldap_define_opt (LDAP_OPT_X_TLS_REQUIRE_CERT); #endif #ifdef LDAP_OPT_X_TLS rb_ldap_define_opt (LDAP_OPT_X_TLS); #endif #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN rb_ldap_define_opt (LDAP_OPT_X_TLS_PROTOCOL_MIN); #endif #ifdef LDAP_OPT_X_TLS_CIPHER_SUITE rb_ldap_define_opt (LDAP_OPT_X_TLS_CIPHER_SUITE); #endif #ifdef LDAP_OPT_X_TLS_RANDOM_FILE rb_ldap_define_opt (LDAP_OPT_X_TLS_RANDOM_FILE); #endif #ifdef LDAP_OPT_X_TLS_NEVER rb_ldap_define_opt (LDAP_OPT_X_TLS_NEVER); #endif #ifdef LDAP_OPT_X_TLS_HARD rb_ldap_define_opt (LDAP_OPT_X_TLS_HARD); #endif #ifdef LDAP_OPT_X_TLS_DEMAND rb_ldap_define_opt (LDAP_OPT_X_TLS_DEMAND); #endif #ifdef LDAP_OPT_X_TLS_ALLOW rb_ldap_define_opt (LDAP_OPT_X_TLS_ALLOW); #endif #ifdef LDAP_OPT_X_TLS_TRY rb_ldap_define_opt (LDAP_OPT_X_TLS_TRY); #endif #ifdef LDAP_OPT_X_SASL_MECH rb_ldap_define_opt (LDAP_OPT_X_SASL_MECH); #endif #ifdef LDAP_OPT_X_SASL_REALM rb_ldap_define_opt (LDAP_OPT_X_SASL_REALM); #endif #ifdef LDAP_OPT_X_SASL_AUTHCID rb_ldap_define_opt (LDAP_OPT_X_SASL_AUTHCID); #endif #ifdef LDAP_OPT_X_SASL_AUTHZID rb_ldap_define_opt (LDAP_OPT_X_SASL_AUTHZID); #endif #ifdef LDAP_OPT_X_SASL_SSF rb_ldap_define_opt (LDAP_OPT_X_SASL_SSF); #endif #ifdef LDAP_OPT_X_SASL_SSF_EXTERNAL rb_ldap_define_opt (LDAP_OPT_X_SASL_SSF_EXTERNAL); #endif #ifdef LDAP_OPT_X_SASL_SECPROPS rb_ldap_define_opt (LDAP_OPT_X_SASL_SECPROPS); #endif #ifdef LDAP_OPT_X_SASL_SSF_MIN rb_ldap_define_opt (LDAP_OPT_X_SASL_SSF_MIN); #endif #ifdef LDAP_OPT_X_SASL_SSF_MAX rb_ldap_define_opt (LDAP_OPT_X_SASL_SSF_MAX); #endif #ifdef LDAP_OPT_X_SASL_MAXBUFSIZE rb_ldap_define_opt (LDAP_OPT_X_SASL_MAXBUFSIZE); #endif #endif /* USE_OPENLDAP2 */ #undef rb_ldap_define_opt /* these constants indicate search scopes */ #define rb_ldap_define_scope(scope) rb_define_const(rb_mLDAP,#scope,INT2NUM(scope)) rb_ldap_define_scope (LDAP_SCOPE_BASE); rb_ldap_define_scope (LDAP_SCOPE_SUBTREE); rb_ldap_define_scope (LDAP_SCOPE_ONELEVEL); #undef rb_ldap_define_scope #define rb_ldap_define_deref(x) rb_define_const(rb_mLDAP,#x,INT2NUM(x)) #ifdef LDAP_DEREF_NEVER rb_ldap_define_deref (LDAP_DEREF_NEVER); #endif #ifdef LDAP_DEREF_SEARCHING rb_ldap_define_deref (LDAP_DEREF_SEARCHING); #endif #ifdef LDAP_DEREF_FINDING rb_ldap_define_deref (LDAP_DEREF_FINDING); #endif #ifdef LDAP_DEREF_ALWAYS rb_ldap_define_deref (LDAP_DEREF_ALWAYS); #endif #undef rb_ldap_define_deref #define rb_ldap_define_sasl_mech(c) \ (c ? rb_define_const(rb_mLDAP,#c,rb_str_new2(c)) : rb_define_const(rb_mLDAP,#c,Qnil)) #ifdef LDAP_SASL_SIMPLE rb_ldap_define_sasl_mech (LDAP_SASL_SIMPLE); #endif #undef rb_ldap_define_sasl_mech #define rb_ldap_define_auth_method(c) rb_define_const(rb_mLDAP,#c,INT2NUM(c)) rb_ldap_define_auth_method (LDAP_AUTH_NONE); rb_ldap_define_auth_method (LDAP_AUTH_SIMPLE); #ifdef LDAP_AUTH_KRBV41 rb_ldap_define_auth_method (LDAP_AUTH_KRBV41); #endif #ifdef LDAP_AUTH_KRBV42 rb_ldap_define_auth_method (LDAP_AUTH_KRBV42); #endif #ifdef LDAP_AUTH_SASL rb_ldap_define_auth_method (LDAP_AUTH_SASL); #endif #ifdef LDAP_KRBV4 rb_ldap_define_auth_method (LDAP_KRBV4); #endif /* wldap32.h */ #ifdef LDAP_AUTH_OTHERKIND rb_ldap_define_auth_method (LDAP_AUTH_OTHERKIND); #endif #ifdef LDAP_AUTH_DPA rb_ldap_define_auth_method (LDAP_AUTH_DPA); #endif #ifdef LDAP_AUTH_MSN rb_ldap_define_auth_method (LDAP_AUTH_MSN); #endif #ifdef LDAP_AUTH_NEGOTIATE rb_ldap_define_auth_method (LDAP_AUTH_NEGOTIATE); #endif #ifdef LDAP_AUTH_NTLM rb_ldap_define_auth_method (LDAP_AUTH_NTLM); #endif #ifdef LDAP_AUTH_SICILY rb_ldap_define_auth_method (LDAP_AUTH_SICILY); #endif #ifdef LDAP_AUTH_SSPI rb_ldap_define_auth_method (LDAP_AUTH_SSPI); #endif #undef rb_ldap_define_auth_method #ifdef LDAP_CONTROL_PAGEDRESULTS rb_define_const (rb_mLDAP, "LDAP_CONTROL_PAGEDRESULTS", rb_str_new2 (LDAP_CONTROL_PAGEDRESULTS)); #endif #define rb_ldap_define_const(c) rb_define_const(rb_mLDAP,#c,INT2NUM(c)) rb_ldap_define_const (LDAP_MOD_ADD); rb_ldap_define_const (LDAP_MOD_DELETE); rb_ldap_define_const (LDAP_MOD_REPLACE); rb_ldap_define_const (LDAP_MOD_BVALUES); #ifdef LDAP_MOD_INCREMENT /* * See http://www.ietf.org/internet-drafts/draft-zeilenga-ldap-incr-00.txt */ rb_ldap_define_const (LDAP_MOD_INCREMENT); #endif #ifdef LDAP_MOD_OP rb_ldap_define_const (LDAP_MOD_OP); #endif #undef rb_ldap_define_const Init_ldap_conn (); Init_ldap_sslconn (); Init_ldap_saslconn (); #ifdef USE_SSL_CLIENTAUTH Init_ldap_clientauth(); #endif Init_ldap_entry (); Init_ldap_mod (); Init_ldap_misc (); } ruby-ldap-0.9.16/lib/0000755000004100000410000000000012260553634014312 5ustar www-datawww-dataruby-ldap-0.9.16/lib/ldap/0000755000004100000410000000000012260553634015232 5ustar www-datawww-dataruby-ldap-0.9.16/lib/ldap/ldif.rb0000644000004100000410000003710612260553634016504 0ustar www-datawww-data# encoding: US-ASCII # Manipulation of LDIF data. # #-- # $Id: ldif.rb,v 1.11 2005/03/03 01:32:07 ianmacd Exp $ #++ # # Copyright (C) 2005 Ian Macdonald # module LDAP # Record objects are embodiments of LDAP operations. They possess a DN, # a change type (*LDAP_MOD_ADD*, *LDAP_MOD_DELETE* or *LDAP_MOD_REPLACE* # [any of which can be logically AND'ed with *LDAP_MOD_BVALUES*]), a hash of # attributes and value arrays, a hash of modification operations (useful # only when the change type is *LDAP_MOD_REPLACE*) and an array of # LDAP controls. # # The Record class's primary use is as a transitional medium for LDIF # operations parsed by the LDAP::LDIF module. You are unlikely to want to # use it in application code. # class Record attr_reader :dn, :change_type, :attrs, :mods, :controls def initialize(dn, change_type, attrs, mods=nil, ctls=nil) @dn = dn @change_type = change_type @attrs = attrs @mods = mods @controls = ctls end # Send the operation embodied in the Record object to the LDAP::Conn # object specified in +conn+. # def send( conn ) if @change_type == :MODRDN # TODO: How do we deal with 'newsuperior'? # The LDAP API's ldap_modrdn2_s() function doesn't seem to use it. return conn.modrdn( @dn, @attrs['newrdn'], @attrs['deleteoldrdn'] ) end # Mask out the LDAP_MOD_BVALUES bit, as it's irrelevant here. case @change_type & ~LDAP_MOD_BVALUES when LDAP_MOD_ADD @controls == [] ? conn.add( @dn, @attrs ) : conn.add_ext( @dn, @attrs, @controls, [] ) when LDAP_MOD_DELETE @controls == [] ? conn.delete( @dn ) : conn.delete_ext( @dn, @controls, [] ) when LDAP_MOD_REPLACE @controls == [] ? conn.modify( @dn, @mods ) : conn.modify_ext( @dn, @mods, @controls, [] ) end self end # Remove common operational attributes from a Record object. This is # useful if you have Record objects formed from LDIF data that contained # operational attributes. Using LDAP::Record#send to send such an object # to an LDAP server is likely to meet with an exception unless the data is # first cleaned. # # In addition, attributes with duplicate values are pruned, as this can # also result in an exception. # def clean # TODO: These operational attributes are those commonly used by # OpenLDAP 2.2. Others should probably be supported. # %w[ creatorsname createtimestamp modifiersname modifytimestamp entrycsn entryuuid structuralobjectclass ].each do |attr| @attrs.delete( attr ) end # Clean out duplicate attribute values. @attrs.each_key { |k| @attrs[k].uniq! } self end end # This module provides the ability to process LDIF entries and files. # module LDIF LINE_LENGTH = 77 private class Entry < String; end class Mod < String; end class LDIFError < LDAP::Error; end # return *true* if +str+ contains a character with an ASCII value > 127 or # a NUL, LF or CR. Otherwise, *false* is returned. # def LDIF.unsafe_char?( str ) # This could be written as a single regex, but this is faster. str =~ /^[ :]/ || str =~ /[\x00-\x1f\x7f-\xff]/ end # Perform Base64 decoding of +str+. If +concat+ is *true*, LF characters # are stripped. # def LDIF.base64_encode( str, concat=false ) str = [ str ].pack( 'm' ) str.gsub!( /\n/, '' ) if concat str end # Perform Base64 encoding of +str+. # def LDIF.base64_decode( str ) str.unpack( 'm*' )[0] end # Read a file from the URL +url+. At this time, the only type of URL # supported is the +file://+ URL. # def LDIF.read_file( url ) unless url.sub!( %r(^file://), '' ) raise ArgumentError, "Bad external file reference: #{url}" end # Slurp an external file. # TODO: Support other URL types in the future. File.open( url ).readlines( nil )[0] end # This converts an attribute and array of values to LDIF. # def LDIF.to_ldif( attr, vals ) ldif = '' vals.each do |val| sep = ':' if unsafe_char?( val ) sep = '::' val = base64_encode( val, true ) end firstline_len = LINE_LENGTH - ( "%s%s " % [ attr, sep ] ).length ldif << "%s%s %s\n" % [ attr, sep, val.slice!( 0..firstline_len ) ] while val.length > 0 ldif << " %s\n" % val.slice!( 0..LINE_LENGTH - 1 ) end end ldif end public # Parse the LDIF entry contained in +lines+ and return an LDAP::Record # object. +lines+ should be an object that responds to each, such as a # string or an array of lines, separated by \n characters. # def LDIF.parse_entry( lines ) header = true comment = false change_type = nil sep = nil attr = nil bvalues = [] controls = nil hash = {} mods = {} mod_type = nil lines.each do |line| # Skip (continued) comments. if line =~ /^#/ || ( comment && line[0..0] == ' ' ) comment = true next end # Skip blank lines. next if line =~ /^$/ # Reset mod type if this entry has more than one mod to make. # A '-' continuation is only valid if we've already had a # 'changetype: modify' line. if line =~ /^-$/ && change_type == LDAP_MOD_REPLACE next end line.chomp! # N.B. Attributes and values can be separated by one or two colons, # or one colon and a '<'. Either of these is then followed by zero # or one spaces. if md = line.match( /^[^ ].*?((:[:<]?) ?)/ ) # If previous value was Base64-encoded and is not continued, # we need to decode it now. if sep == '::' if mod_type mods[mod_type][attr][-1] = base64_decode( mods[mod_type][attr][-1] ) bvalues << attr if unsafe_char?( mods[mod_type][attr][-1] ) else hash[attr][-1] = base64_decode( hash[attr][-1] ) bvalues << attr if unsafe_char?( hash[attr][-1] ) end end # Found a attr/value line. attr, val = line.split( md[1], 2 ) attr.downcase! # Attribute must be ldap-oid / (ALPHA *(attr-type-chars)) if attr !~ /^(?:(?:\d+\.)*\d+|[[:alnum:]-]+)(?:;[[:alnum:]-]+)*$/ raise LDIFError, "Invalid attribute: #{attr}" end if attr == 'dn' header = false change_type = nil controls = [] end sep = md[2] val = read_file( val ) if sep == ':<' case attr when 'version' # Check the LDIF version. if header if val != '1' raise LDIFError, "Unsupported LDIF version: #{val}" else header = false next end end when 'changetype' change_type = case val when 'add' then LDAP_MOD_ADD when 'delete' then LDAP_MOD_DELETE when 'modify' then LDAP_MOD_REPLACE when /^modr?dn$/ then :MODRDN end raise LDIFError, "Invalid change type: #{attr}" unless change_type when 'add', 'delete', 'replace' unless change_type == LDAP_MOD_REPLACE raise LDIFError, "Cannot #{attr} here." end mod_type = case attr when 'add' then LDAP_MOD_ADD when 'delete' then LDAP_MOD_DELETE when 'replace' then LDAP_MOD_REPLACE end # In this case val is actually an attribute and should be lowercased. mods[mod_type] ||= {} mods[mod_type][val.downcase] ||= [] when 'control' oid, criticality = val.split( / /, 2 ) unless oid =~ /(?:\d+\.)*\d+/ raise LDIFError, "Bad control OID: #{oid}" end if criticality md = criticality.match( /(:[:<]?) ?/ ) ctl_sep = md[1] if md criticality, value = criticality.split( /:[:<]? ?/, 2 ) if criticality !~ /^(?:true|false)$/ raise LDIFError, "Bad control criticality: #{criticality}" end # Convert 'true' or 'false'. to_boolean would be nice. :-) criticality = eval( criticality ) end if value value = base64_decode( value ) if ctl_sep == '::' value = read_file( value ) if ctl_sep == ':<' value = Control.encode( value ) end controls << Control.new( oid, value, criticality ) else # Convert modrdn's deleteoldrdn from '1' to true, anything else # to false. Should probably raise an exception if not '0' or '1'. # if change_type == :MODRDN && attr == 'deleteoldrdn' val = val == '1' ? true : false end if change_type == LDAP_MOD_REPLACE mods[mod_type][attr] << val else hash[attr] ||= [] hash[attr] << val end comment = false # Make a note of this attribute if value is binary. bvalues << attr if unsafe_char?( val ) end else # Check last line's separator: if not a binary value, the # continuation line must be indented. If a comment makes it this # far, that's also an error. # if sep == ':' && line[0..0] != ' ' || comment raise LDIFError, "Improperly continued line: #{line}" end # OK; this is a valid continuation line. # Append line except for initial space. line[0] = '' if line[0..0] == ' ' if change_type == LDAP_MOD_REPLACE # Append to last value of current mod type. mods[mod_type][attr][-1] << line else # Append to last value. hash[attr][-1] << line end end end # If last value in LDIF entry was Base64-encoded, we need to decode # it now. if sep == '::' if mod_type mods[mod_type][attr][-1] = base64_decode( mods[mod_type][attr][-1] ) bvalues << attr if unsafe_char?( mods[mod_type][attr][-1] ) else hash[attr][-1] = base64_decode( hash[attr][-1] ) bvalues << attr if unsafe_char?( hash[attr][-1] ) end end # Remove and remember DN. dn = hash.delete( 'dn' )[0] # This doesn't really matter, but let's be anal about it, because it's # not an attribute and doesn't belong here. bvalues.delete( 'dn' ) # If there's no change type, it's just plain LDIF data, so we'll treat # it like an addition. change_type ||= LDAP_MOD_ADD case change_type when LDAP_MOD_ADD mods[LDAP_MOD_ADD] = [] hash.each do |attr_local, val| if bvalues.include?( attr_local ) ct = LDAP_MOD_ADD | LDAP_MOD_BVALUES else ct = LDAP_MOD_ADD end mods[LDAP_MOD_ADD] << LDAP.mod( ct, attr_local, val ) end when LDAP_MOD_DELETE # Nothing to do. when LDAP_MOD_REPLACE raise LDIFError, "mods should not be empty" if mods == {} new_mods = {} mods.each do |mod_type_local,attrs| attrs.each_key do |attr_local| if bvalues.include?( attr_local ) mt = mod_type_local | LDAP_MOD_BVALUES else mt = mod_type_local end new_mods[mt] ||= {} new_mods[mt][attr_local] = mods[mod_type_local][attr_local] end end mods = new_mods when :MODRDN # Nothing to do. end Record.new( dn, change_type, hash, mods, controls ) end # Open and parse a file containing LDIF entries. +file+ should be a string # containing the path to the file. If +sort+ is true, the resulting array # of LDAP::Record objects will be sorted on DN length, which can be useful # to avoid a later attempt to process an entry whose parent does not yet # exist. This can easily happen if your LDIF file is unordered, which is # likely if it was produced with a tool such as slapcat(8). # # If a block is given, each LDAP::Record object will be yielded to the # block and *nil* will be returned instead of the array. This is much less # memory-intensive when parsing a large LDIF file. # def LDIF.parse_file( file, sort=false ) # :yield: record File.open( file ) do |f| entries = [] entry = false header = true version = false while line = f.gets if line =~ /^dn:/ header = false if entry && ! version if block_given? yield parse_entry( entry ) else entries << parse_entry( entry ) end end if version entry << line version = false else entry = [ line ] end next end if header && line.downcase =~ /^version/ entry = [ line ] version = true next end entry << line end if block_given? yield parse_entry( entry ) nil else entries << parse_entry( entry ) # Sort entries if sorting has been requested. entries.sort! { |x,y| x.dn.length <=> y.dn.length } if sort entries end end end # Given the DN, +dn+, convert a single LDAP::Mod or an array of # LDAP::Mod objects, given in +mods+, to LDIF. # def LDIF.mods_to_ldif( dn, *mods ) ldif = "dn: %s\nchangetype: modify\n" % dn plural = false mods.flatten.each do |mod| # TODO: Need to dynamically assemble this case statement to add # OpenLDAP's increment change type, etc. change_type = case mod.mod_op & ~LDAP_MOD_BVALUES when LDAP_MOD_ADD then 'add' when LDAP_MOD_DELETE then 'delete' when LDAP_MOD_REPLACE then 'replace' end ldif << "-\n" if plural ldif << LDIF.to_ldif( change_type, [mod.mod_type] ) ldif << LDIF.to_ldif( mod.mod_type, mod.mod_vals ) plural = true end LDIF::Mod.new( ldif ) end end class Entry # Convert an LDAP::Entry to LDIF. # def to_ldif ldif = "dn: %s\n" % get_dn get_attributes.each do |attr| get_values( attr ).each do |val| ldif << LDIF.to_ldif( attr, [ val ] ) end end LDIF::Entry.new( ldif ) end alias_method :to_s, :to_ldif end class Mod # Convert an LDAP::Mod with the DN given in +dn+ to LDIF. # def to_ldif( dn ) ldif = "dn: %s\n" % dn # TODO: Need to dynamically assemble this case statement to add # OpenLDAP's increment change type, etc. case mod_op & ~LDAP_MOD_BVALUES when LDAP_MOD_ADD ldif << "changetype: add\n" when LDAP_MOD_DELETE ldif << "changetype: delete\n" when LDAP_MOD_REPLACE return LDIF.mods_to_ldif( dn, self ) end ldif << LDIF.to_ldif( mod_type, mod_vals ) LDIF::Mod.new( ldif ) end alias_method :to_s, :to_ldif end end ruby-ldap-0.9.16/lib/ldap/schema.rb0000644000004100000410000000732212260553634017023 0ustar www-datawww-data# Manipulation of LDAP schema data. # #-- # $Id: schema.rb,v 1.9 2006/02/08 23:15:17 ianmacd Exp $ #++ # The LDAP module encapsulates the various LDAP-related classes in their own # namespace. # module LDAP # Retrieve and process information pertaining to LDAP schemas. # class Schema < Hash def initialize(entry) if( entry ) entry.each do |key, vals| self[key] = vals end end end # Return the list of values related to the schema component given in # +key+. See LDAP::Conn#schema for common values of +key+. # def names(key) self[key].collect{|val| val =~ /NAME\s+'([\w\d_\-]+)'/; $1} end # Return the list of attributes in object class +oc+ that are of category # +at+. +at+ may be the string *MUST*, *MAY* or *SUP*. # def attr(oc,at) self['objectClasses'].each do |s| if( s =~ /NAME\s+'#{oc}'/ ) case s when /#{at}\s+\(([\w\d_\-\s\$]+)\)/i then return $1.split("$").collect{|attr| attr.strip} when /#{at}\s+([\w\d_\-]+)/i then return $1.split("$").collect{|attr| attr.strip} end end end return nil end # Return the list of attributes that an entry with object class +oc+ # _must_ possess. # def must(oc) attr(oc, "MUST") end # Return the list of attributes that an entry with object class +oc+ # _may_ possess. # def may(oc) attr(oc, "MAY") end # Return the superior object class of object class +oc+. # def sup(oc) attr(oc, "SUP") end end class Conn # Fetch the schema data for the connection. # # If +base+ is given, it gives the base DN for the search. +attrs+, if # given, is an array of attributes that should be returned from the # server. The default list is *objectClasses*, *attributeTypes*, # *matchingRules*, *matchingRuleUse*, *dITStructureRules*, # *dITContentRules*, *nameForms* and *ldapSyntaxes*. # # +sec+ and +usec+ can be used to specify a time-out for the search in # seconds and microseconds, respectively. # def schema(base = nil, attrs = nil, sec = 0, usec = 0) attrs ||= [ 'objectClasses', 'attributeTypes', 'matchingRules', 'matchingRuleUse', 'dITStructureRules', 'dITContentRules', 'nameForms', 'ldapSyntaxes', ] base ||= root_dse(['subschemaSubentry'], sec, usec)[0]['subschemaSubentry'][0] base ||= 'cn=schema' entries = search2(base, LDAP_SCOPE_BASE, '(objectClass=subschema)', attrs, false, sec, usec) return Schema.new(entries[0]) end # Fetch the root DSE (DSA-specific Entry) for the connection. DSA stands # for Directory System Agent and simply refers to the LDAP server you are # using. # # +attrs+, if given, is an array of attributes that should be returned # from the server. The default list is *subschemaSubentry*, # *namingContexts*, *monitorContext*, *altServer*, *supportedControl*, # *supportedExtension*, *supportedFeatures*, *supportedSASLMechanisms* # and *supportedLDAPVersion*. # # +sec+ and +usec+ can be used to specify a time-out for the search in # seconds and microseconds, respectively. # def root_dse(attrs = nil, sec = 0, usec = 0) attrs ||= [ 'subschemaSubentry', 'namingContexts', 'monitorContext', 'altServer', 'supportedControl', 'supportedExtension', 'supportedFeatures', 'supportedSASLMechanisms', 'supportedLDAPVersion', ] entries = search2('', LDAP_SCOPE_BASE, '(objectClass=*)', attrs, false, sec, usec) return entries end end end ruby-ldap-0.9.16/lib/ldap/control.rb0000644000004100000410000000172512260553634017244 0ustar www-datawww-data# Manipulation of LDAP control data. # #-- # $Id: control.rb,v 1.2 2005/02/28 05:02:25 ianmacd Exp $ #++ # # Copyright (C) 2004 Ian Macdonald # module LDAP class Control require 'openssl' # Take +vals+, produce an Array of values in ASN.1 format and then # convert the Array to DER. # def Control.encode( *vals ) encoded_vals = [] vals.each do |val| encoded_vals << case val when Integer OpenSSL::ASN1::Integer( val ) when String OpenSSL::ASN1::OctetString.new( val ) else # What other types may exist? end end OpenSSL::ASN1::Sequence.new( encoded_vals ).to_der end # Take an Array of ASN.1 data and return an Array of decoded values. # def decode values = [] OpenSSL::ASN1::decode( self.value ).value.each do |val| values << val.value end values end end end ruby-ldap-0.9.16/NOTES0000644000004100000410000001067712260553634014372 0ustar www-datawww-data0.9.16 ----- * Fixed undefined method 'each' in LDAP::LDIF.mods_to_ldif (GH-26). Thanks to Francesco Malvezzi. 0.9.15 ----- * Accept nil for new_parent_dn for rename. Thanks to Kouhei Sutou. 0.9.14 ----- * Fixed option parsing bug for LDAP::Conn.sasl_bind. Thanks to Brian Leake. * Added possibility to use :nocanon option in rb_ldap_conn_sasl_bind. See ldap_set_option(3) for more information. Thanks to Brian Leake. * Added function conn.rename(dn, new_rdn, new_parent_dn, delete_old_rdn, sctrls, cctrls) => self Modify the RDN of the entry with DN, dn, giving it the new RDN in parent new_parent_dn, new_rdn. If delete_old_rdn is true, the old RDN value will be deleted from the entry. Thanks to Marek Veber. * Added option LDAP_OPT_NETWORK_TIMEOUT for openLDAP. Thanks to David Campbell. * Fixed build error with GCC 4.8.1. Thanks to Kouhei Sutou. * Add missing ldap_raname_s() function availability check. Thanks to Kouhei Sutou. 0.9.13 ----- * Prevent SyntaxError raised under Ruby 2.0.0 by line 107 regex (invalid multibyte escape) 0.9.12 ----- * On windows, the default ldap library became wldap32; * Fixed compile with ruby 1.9.2. Thank to Hiroki Najima! * Fixed many memory leaks; * Added functions: LDAP::Conn.open_uri(uri); LDAP::explode_dn(dn, notypes); LDAP::explode_rdn(rdn, notypes). Thanks to Marek Veber and Antonio Terceiro! * Fixed bug in ldap/ldif.rb (GH-6). Thanks to bbense. * Fixed LDAP::Mod data corruption. Thanks to Aprotim Sanyal! * Enable client certificate authentication for mozilla ldap 6.0 only. Thanks to Yuri Arabadji! 0.9.11 ----- Allow passing SASL interaction options This adds a hash parameter "options" to LDAP::Conn.sasl_bind, which can take :authzid, :authcid, and :realm (and corresponding strings), for SASL authentication. Also, refactored the rb_scan_args inside rb_ldap_conn_sasl_bind to use C's case fallthrough, leading to less code repetition. Tnahks to Anthony M. Martinez. 0.9.10 ----- Added controls and referral extraction to #search_ext and #search_ext2. Thanks to Michael Granger. 0.9.9 ----- Supported OpenLDAP 2.4.15 and higher. Thanks to Milos Jakubicek. Gem Packaging Support. Thanks to S. Potter [mbbx6spp]. 0.9.8 ----- Supported Ruby 1.9.x. 0.9.7 ----- LDAP_MOD_DELETE and LDAP_MOD_REPLACE were reversed in win/winldap.h, so deletion and replacement operations did not work on Win32 systems. 0.9.6 ----- A segfault on FreeBSD when using AMD64 was fixed for this release. The only other changes are minor clarifications of the documentation. 0.9.5 ----- The Windows build is now believed to work out of the box. It has been tested on Windows XP SP2, using SVC C++ 6.0 to build the software. Thanks to Chris Scharf for his work in this area and willingness to work with me on fixing the problems. 0.9.4 ----- LDAP::Conn#search, LDAP::Conn#search2, LDAP::Conn#search_ext and LDAP::Conn#search_ext2 have been modified to treat LDAP_SIZELIMIT_EXCEEDED as success. After using any of these four methods, the user should use LDAP::Conn#err to check whether the error status of the Conn object is LDAP::LDAP_SIZELIMIT_EXCEEDED. If true, the results set has been truncated by the server. Previously, LDAP_SIZELIMIT_EXCEEDED would raise an exception and no results would be returned, which is not the correct behaviour if the user has deliberately put a limit on the number of results to be returned, as might be done in order to spare the server. 0.9.3 ----- The usability of the library on Windows platforms is currently a case of 'suck it and see'. Some people report the code working, others report immediate segfaults; yet others say that it worked after they made some minor alterations to the code in order to get it to build. Differences in Windows platform used, chosen compiler and version, plus the variety of servers with which the code is used, conspire to result in the exact facts of the matter not yet having been ascertained. Most people seemed to experience some difficulty in getting the code to build on Windows, so some effort has gone into making this better for the 0.9.3 release. This work is difficult, since I do not have a Windows build environment at my disposal. If you are a Windows user and you found that the code did not work in its original form, but you managed to get it to work after some alterations, I would be very grateful if you wrote to me to let me know what changes were needed. Please include precise details of your build platform. ruby-ldap-0.9.16/sslconn.c0000644000004100000410000002255312260553634015376 0ustar www-datawww-data/* * sslconn.c * $Id: sslconn.c,v 1.18 2006/04/19 22:13:26 ianmacd Exp $ */ #include "ruby.h" #include "rbldap.h" #if defined(HAVE_SYS_TIME_H) # include #endif #if defined(HAVE_UNISTD_H) # include #endif #if defined(HAVE_LDAP_START_TLS_S) # define USE_OPENLDAP_SSLCONN #elif defined(HAVE_LDAPSSL_INIT) # define USE_NSSLDAP_SSLCONN #elif defined(HAVE_LDAP_SSLINIT) # define USE_WLDAP32_SSLCONN #endif VALUE rb_cLDAP_SSLConn; #ifdef USE_OPENLDAP_SSLCONN static VALUE rb_openldap_sslconn_initialize (int argc, VALUE argv[], VALUE self) { RB_LDAP_DATA *ldapdata; LDAP *cldap; char *chost = NULL; int cport = LDAP_PORT; VALUE arg1, arg2, arg3, arg4, arg5; LDAPControl **serverctrls = NULL; LDAPControl **clientctrls = NULL; int version; int start_tls; Data_Get_Struct (self, RB_LDAP_DATA, ldapdata); if (ldapdata->ldap) return Qnil; switch (rb_scan_args (argc, argv, "05", &arg1, &arg2, &arg3, &arg4, &arg5)) { case 0: chost = ALLOCA_N (char, strlen ("localhost") + 1); strcpy (chost, "localhost"); cport = LDAP_PORT; start_tls = 0; break; case 1: chost = StringValueCStr (arg1); cport = LDAP_PORT; start_tls = 0; break; case 2: chost = StringValueCStr (arg1); cport = NUM2INT (arg2); start_tls = 0; break; case 3: chost = StringValueCStr (arg1); cport = NUM2INT (arg2); start_tls = (arg3 == Qtrue) ? 1 : 0; break; case 4: chost = StringValueCStr (arg1); cport = NUM2INT (arg2); start_tls = (arg3 == Qtrue) ? 1 : 0; serverctrls = rb_ldap_get_controls (arg4); break; case 5: chost = StringValueCStr (arg1); cport = NUM2INT (arg2); start_tls = (arg3 == Qtrue) ? 1 : 0; serverctrls = rb_ldap_get_controls (arg4); clientctrls = rb_ldap_get_controls (arg5); break; default: rb_bug ("rb_ldap_conn_new"); } cldap = ldap_init (chost, cport); if (!cldap) rb_raise (rb_eLDAP_ResultError, "can't initialise an LDAP session"); ldapdata->ldap = cldap; if (rb_block_given_p ()) { rb_yield (self); } ldap_get_option (cldap, LDAP_OPT_PROTOCOL_VERSION, &version); if (version < LDAP_VERSION3) { version = LDAP_VERSION3; ldapdata->err = ldap_set_option (cldap, LDAP_OPT_PROTOCOL_VERSION, &version); Check_LDAP_Result (ldapdata->err); } if (start_tls) { ldapdata->err = ldap_start_tls_s (cldap, serverctrls, clientctrls); Check_LDAP_Result (ldapdata->err); } else { int opt = LDAP_OPT_X_TLS_HARD; ldapdata->err = ldap_set_option (cldap, LDAP_OPT_X_TLS, &opt); Check_LDAP_Result (ldapdata->err); } rb_iv_set (self, "@args", rb_ary_new4 (argc, argv)); rb_iv_set (self, "@sasl_quiet", Qfalse); return Qnil; } #endif /* USE_OPENLDAP_SSLCONN */ #ifdef USE_NSSLDAP_SSLCONN static VALUE rb_nssldap_sslconn_initialize (int argc, VALUE argv[], VALUE self) { RB_LDAP_DATA *ldapdata; LDAP *cldap; char *chost = NULL; char *certpath = NULL; int cport = LDAP_PORT; int csecure = 0; VALUE arg1, arg2, arg3, arg4; Data_Get_Struct (self, RB_LDAP_DATA, ldapdata); if (ldapdata->ldap) return Qnil; switch (rb_scan_args (argc, argv, "04", &arg1, &arg2, &arg3, &arg4)) { case 0: chost = ALLOCA_N (char, strlen ("localhost") + 1); strcpy (chost, "localhost"); cport = LDAP_PORT; csecure = 0; certpath = NULL; break; case 1: chost = StringValueCStr (arg1); cport = LDAP_PORT; csecure = 0; certpath = NULL; break; case 2: chost = StringValueCStr (arg1); cport = NUM2INT (arg2); csecure = 0; certpath = NULL; break; case 3: chost = StringValueCStr (arg1); cport = NUM2INT (arg2); csecure = (arg3 == Qtrue) ? 1 : 0; certpath = NULL; break; case 4: chost = StringValueCStr (arg1); cport = NUM2INT (arg2); csecure = (arg3 == Qtrue) ? 1 : 0; certpath = (arg4 == Qnil) ? NULL : StringValueCStr (arg4); break; default: rb_bug ("rb_ldap_conn_new"); } /*** ldapssl_client_init(): http://docs.iplanet.com/docs/manuals/dirsdk/csdk41/html/function.htm#25963 ldapssl_client_authinit(): http://docs.iplanet.com/docs/manuals/dirsdk/csdk41/html/function.htm#26024 ***/ ldapssl_client_init (certpath, NULL); cldap = ldapssl_init (chost, cport, csecure); ldapdata->ldap = cldap; rb_iv_set (self, "@args", Qnil); return Qnil; } #endif /* USE_NSSLDAP_SSLCONN */ #if defined(USE_WLDAP32_SSLCONN) static VALUE rb_wldap32_sslconn_initialize (int argc, VALUE argv[], VALUE self) { RB_LDAP_DATA *ldapdata; LDAP *cldap; char *chost; int cport; int csecure; int version; VALUE arg1, arg2, arg3; Data_Get_Struct (self, RB_LDAP_DATA, ldapdata); if (ldapdata->ldap) return Qnil; switch (rb_scan_args (argc, argv, "02", &arg1, &arg2, &arg3)) { case 0: chost = ALLOCA_N (char, strlen ("localhost") + 1); strcpy (chost, "localhost"); cport = LDAP_PORT; csecure = 1; break; case 1: chost = StringValueCStr (arg1); cport = LDAP_PORT; csecure = 1; break; case 2: chost = StringValueCStr (arg1); cport = NUM2INT (arg2); csecure = 1; break; case 3: chost = StringValueCStr (arg1); cport = NUM2INT (arg2); csecure = (arg3 == Qtrue) ? 1 : 0; break; default: rb_bug ("rb_ldap_conn_new"); } cldap = ldap_sslinit (chost, cport, csecure); ldapdata->ldap = cldap; #if defined(HAVE_LDAP_GET_OPTION) && defined(HAVE_LDAP_SET_OPTION) ldap_get_option (cldap, LDAP_OPT_PROTOCOL_VERSION, &version); if (version < LDAP_VERSION3) { version = LDAP_VERSION3; ldapdata->err = ldap_set_option (cldap, LDAP_OPT_PROTOCOL_VERSION, &version); Check_LDAP_Result (ldapdata->err); } #endif rb_iv_set (self, "@args", Qnil); return Qnil; } VALUE rb_ldap_sslconn_bind_f (int argc, VALUE argv[], VALUE self, VALUE (*rb_ldap_sslconn_bind_func) (int, VALUE[], VALUE)) { RB_LDAP_DATA *ldapdata; Data_Get_Struct (self, RB_LDAP_DATA, ldapdata); if (!ldapdata->ldap) { if (rb_iv_get (self, "@args") != Qnil) { rb_ldap_conn_rebind (self); GET_LDAP_DATA (self, ldapdata); } else { rb_raise (rb_eLDAP_InvalidDataError, "The LDAP handler has already unbound."); } } ldapdata->err = ldap_connect (ldapdata->ldap, NULL); Check_LDAP_Result (ldapdata->err); return rb_ldap_sslconn_bind_func (argc, argv, self); } /* * call-seq: * conn.bind(dn=nil, password=nil, method=LDAP::LDAP_AUTH_SIMPLE) => self * conn.bind(dn=nil, password=nil, method=LDAP::LDAP_AUTH_SIMPLE) * { |conn| } => self * * Bind an LDAP connection, using the DN, +dn+, the credential, +password+, * and the bind method, +method+. If a block is given, +self+ is yielded to * the block. */ VALUE rb_ldap_sslconn_bind_s (int argc, VALUE argv[], VALUE self) { return rb_ldap_sslconn_bind_f (argc, argv, self, rb_ldap_conn_bind_s); } /* * call-seq: * conn.simple_bind(dn=nil, password=nil) => self * conn.simple_bind(dn=nil, password=nil) { |conn| } => self * * Bind an LDAP connection, using the DN, +dn+, and the credential, +password+. * If a block is given, +self+ is yielded to the block. */ VALUE rb_ldap_sslconn_simple_bind_s (int argc, VALUE argv[], VALUE self) { return rb_ldap_sslconn_bind_f (argc, argv, self, rb_ldap_conn_simple_bind_s); } #endif /* USE_WLDAP32_SSLCONN */ /* * call-seq: * LDAP::SSLConn.new(host='localhost', port=LDAP_PORT, * start_tls=false, sctrls=nil, cctrls=nil) * => LDAP::SSLConn * LDAP::SSLConn.new(host='localhost', port=LDAP_PORT, * start_tls=false, sctrls=nil, cctrls=nil) { |conn| } * => LDAP::SSLConn * * Return a new LDAP::SSLConn connection to the server, +host+, on port +port+. * If +start_tls+ is *true*, START_TLS will be used to establish the * connection, automatically setting the LDAP protocol version to v3 if it is * not already set. * * +sctrls+ is an array of server controls, whilst +cctrls+ is an array of * client controls. */ VALUE rb_ldap_sslconn_initialize (int argc, VALUE argv[], VALUE self) { #if defined(USE_OPENLDAP_SSLCONN) return rb_openldap_sslconn_initialize (argc, argv, self); #elif defined(USE_NSSLDAP_SSLCONN) return rb_nssldap_sslconn_initialize (argc, argv, self); #elif defined(USE_WLDAP32_SSLCONN) return rb_wldap32_sslconn_initialize (argc, argv, self); #else rb_notimplement (); #endif } /* :nodoc: */ VALUE rb_ldap_sslconn_s_open (int argc, VALUE argv[], VALUE klass) { rb_notimplement (); } /* Document-class: LDAP::SSLConn * * Create and manipulate encrypted LDAP connections. LDAP::SSLConn is a * subclass of LDAP::Conn and so has access to the same methods, except for * LDAP::SSLConn.open, which is not implemented. */ void Init_ldap_sslconn () { rb_cLDAP_SSLConn = rb_define_class_under (rb_mLDAP, "SSLConn", rb_cLDAP_Conn); rb_define_singleton_method (rb_cLDAP_SSLConn, "open", rb_ldap_sslconn_s_open, -1); rb_define_method (rb_cLDAP_SSLConn, "initialize", rb_ldap_sslconn_initialize, -1); #ifdef USE_WLDAP32_SSLCONN rb_define_method (rb_cLDAP_SSLConn, "bind", rb_ldap_sslconn_bind_s, -1); rb_define_method (rb_cLDAP_SSLConn, "simple_bind", rb_ldap_sslconn_simple_bind_s, -1); #endif } ruby-ldap-0.9.16/rbldap.h0000644000004100000410000001253312260553634015165 0ustar www-datawww-data/* * rbldap.h * $Id: rbldap.h,v 1.17 2006/08/09 11:23:04 ianmacd Exp $ */ #ifndef RB_LDAP_H #define RB_LDAP_H 1 #ifdef USE_WLDAP32 # ifdef HAVE_WINLBER_H # include "winlber.h" # endif # include "winldap.h" #else # include # include #endif #ifdef HAVE_LDAP_SSL_H #include #endif #ifndef LDAP_OPT_SUCCESS # define LDAP_OPT_SUCCESS (0) # define LDAP_OPT_ERROR (-1) #endif #define RB_LDAP_MAJOR_VERSION 0 #define RB_LDAP_MINOR_VERSION 9 #define RB_LDAP_PATCH_VERSION 16 #define RB_LDAP_VERSION "0.9.16" #define LDAP_GET_OPT_MAX_BUFFER_SIZE (1024) /* >= sizeof(LDAPAPIInfo) */ #define RB_LDAP_SET_STR(var,val) {\ Check_Type(val, T_STRING); \ var = ALLOC_N(char, RSTRING_LEN(val) + 1); \ memcpy(var, RSTRING_PTR(val), RSTRING_LEN(val) + 1); \ } #if defined(HAVE_LDAP_SEARCH_EXT_S) # define HAVE_LDAPCONTROL #endif typedef struct rb_ldap_data { LDAP *ldap; int bind; int err; } RB_LDAP_DATA; #define RLDAP_DATA_PTR(obj) ((RB_LDAP_DATA*)DATA_PTR(obj)) typedef struct rb_ldapentry_data { LDAP *ldap; LDAPMessage *msg; } RB_LDAPENTRY_DATA; typedef struct rb_ldapmod_data { LDAPMod *mod; } RB_LDAPMOD_DATA; struct timeval rb_time_interval(VALUE num); #ifndef HAVE_LDAP_MEMFREE # define ldap_memfree(ptr) free(ptr) #endif extern VALUE rb_mLDAP; extern VALUE rb_sLDAP_APIInfo; extern VALUE rb_cLDAP_Controls; extern VALUE rb_cLDAP_Conn; extern VALUE rb_cLDAP_SSLConn; extern VALUE rb_cLDAP_Entry; extern VALUE rb_cLDAP_Mod; extern VALUE rb_eLDAP_Error; extern VALUE rb_eLDAP_ResultError; extern VALUE rb_eLDAP_InvalidDataError; extern VALUE rb_eLDAP_InvalidEntryError; #ifdef LDAP_OPT_API_INFO VALUE rb_ldap_apiinfo_new (LDAPAPIInfo *); LDAPAPIInfo *rb_ldap_get_apiinfo (VALUE); #endif /* LDAP_OPT_API_INFO */ #ifdef HAVE_LDAPCONTROL VALUE rb_ldap_control_new (LDAPControl *); LDAPControl *rb_ldap_get_control (VALUE); LDAPControl **rb_ldap_get_controls (VALUE); void rb_ldap_free_controls (LDAPControl ** ctrls); #endif VALUE rb_ldap_class_new (int, VALUE[], VALUE); VALUE rb_ldap_dummy_method (int, VALUE[], VALUE); VALUE rb_ldap_err2string (VALUE, VALUE); VALUE rb_ldap_dn2ufn (VALUE, VALUE); VALUE rb_ldap_hash2mods (VALUE, VALUE, VALUE); VALUE rb_ldap_entry2hash (VALUE, VALUE); VALUE rb_ldap_conn_new (VALUE, LDAP *); VALUE rb_ldap_conn_simple_bind_s (int, VALUE[], VALUE); VALUE rb_ldap_conn_bind_s (int, VALUE[], VALUE); VALUE rb_ldap_conn_start_tls_s (int, VALUE[], VALUE); VALUE rb_ldap_conn_unbind (VALUE); VALUE rb_ldap_conn_set_option (VALUE, VALUE, VALUE); VALUE rb_ldap_conn_get_option (VALUE, VALUE); VALUE rb_ldap_conn_perror (VALUE, VALUE); VALUE rb_ldap_conn_result2error (VALUE, VALUE); VALUE rb_ldap_conn_err2string (VALUE, VALUE); VALUE rb_ldap_conn_search_s (int, VALUE[], VALUE); VALUE rb_ldap_conn_search2_s (int, VALUE[], VALUE); VALUE rb_ldap_conn_add_s (VALUE, VALUE, VALUE); VALUE rb_ldap_conn_modify_s (VALUE, VALUE, VALUE); VALUE rb_ldap_conn_modrdn_s (VALUE, VALUE, VALUE, VALUE); VALUE rb_ldap_conn_delete_s (VALUE, VALUE); VALUE rb_ldap_conn_err (VALUE); VALUE rb_ldap_conn_set_sort (VALUE, VALUE, VALUE); VALUE rb_ldap_conn_get_sort (VALUE); VALUE rb_ldap_saslconn_bind (int, VALUE[], VALUE); VALUE rb_ldap_entry_new (LDAP *, LDAPMessage *); VALUE rb_ldap_entry_get_dn (VALUE self); VALUE rb_ldap_entry_get_values (VALUE, VALUE); VALUE rb_ldap_entry_get_attributes (VALUE); VALUE rb_ldap_entry_to_hash (VALUE); VALUE rb_ldap_mod_new (int, char *, char **); VALUE rb_ldap_mod_new2 (int, char *, struct berval **); VALUE rb_ldap_mod_op (VALUE); VALUE rb_ldap_mod_type (VALUE); VALUE rb_ldap_mod_vals (VALUE); #define Check_Kind(obj,klass) {\ if(!rb_obj_is_kind_of(obj,klass))\ rb_raise(rb_eTypeError,"type mismatch");\ }; #define Check_LDAP_Result(err) { \ if( (err) != LDAP_SUCCESS && (err) != LDAP_SIZELIMIT_EXCEEDED ){ \ rb_raise(rb_eLDAP_ResultError, "%s", ldap_err2string(err)); \ } \ } #define Check_LDAP_OPT_Result(err) { \ if( (err) != LDAP_OPT_SUCCESS ){ \ rb_raise(rb_eLDAP_ResultError, "%s", ldap_err2string(err)); \ } \ } #define GET_LDAP_DATA(obj,ptr) {\ Data_Get_Struct(obj, struct rb_ldap_data, ptr); \ if( ! ptr->ldap ){ \ rb_raise(rb_eLDAP_InvalidDataError, "The LDAP handler has already unbound.");\ } \ } #define Check_LDAPENTRY(obj) {\ RB_LDAPENTRY_DATA *ptr; \ Data_Get_Struct(obj, struct rb_ldapmsg_data, ptr); \ if( ! ptr->msg ){ \ VALUE value = rb_inspect(obj); \ rb_raise(rb_eLDAP_InvalidEntryError, "%s is not a valid entry", \ StringValuePtr(value)); \ }; \ } #define GET_LDAPENTRY_DATA(obj,ptr) { \ Data_Get_Struct(obj, struct rb_ldapentry_data, ptr); \ if( ! ptr->msg ){ \ VALUE value = rb_inspect(obj); \ rb_raise(rb_eLDAP_InvalidEntryError, "%s is not a valid entry", \ StringValuePtr(value)); \ }; \ } #define GET_LDAPMOD_DATA(obj,ptr) {\ Data_Get_Struct(obj, struct rb_ldapmod_data, ptr); \ if( ! ptr->mod ) \ rb_raise(rb_eLDAP_InvalidDataError, "The Mod data is not ready for use."); \ } #define rb_ldap_define_class(cname,parent) \ rb_define_class_under(rb_mLDAP,cname,parent) #define rb_ldap_conn_define_method(method,cfunc,argc) \ rb_define_method(rb_cLDAP_Conn,method,cfunc,argc) #define rb_ldap_entry_define_method(method,cfunc,argc) \ rb_define_method(rb_cLDAP_Entry,method,cfunc,argc) #define rb_ldap_mod_define_method(method,cfunc,argc) \ rb_define_method(rb_cLDAP_Mod,method,cfunc,argc) #endif ruby-ldap-0.9.16/metadata.yml0000644000004100000410000000347212260553635016056 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: ruby-ldap version: !ruby/object:Gem::Version version: 0.9.16 platform: ruby authors: - Alexey Chebotar autorequire: bindir: bin cert_chain: [] date: 2013-09-06 00:00:00.000000000 Z dependencies: [] description: ! 'It provides the interface to some LDAP libraries (e.g. OpenLDAP, Netscape SDK and Active Directory). The common API for application development is described in RFC1823 and is supported by Ruby/LDAP. ' email: alexey.chebotar@gmail.com executables: [] extensions: - extconf.rb extra_rdoc_files: [] files: - ChangeLog - COPYING - FAQ - NOTES - README - TODO - test/ext.rb - test/compare.rb - test/bind-sasl.rb - test/misc1.rb - test/add.rb - test/tc_schema.rb - test/add2.rb - test/search.rb - test/add3.rb - test/modrdn.rb - test/bind-ssl.rb - test/setup.rb - test/search3.rb - test/delete.rb - test/search2.rb - test/tc_conn.rb - test/ts_ldap.rb - test/conf.rb - test/misc2.rb - test/bind-ldaps.rb - test/tc_search.rb - test/bind.rb - test/tc_ldif.rb - test/subschema.rb - test/moz_cert.rb - lib/ldap/schema.rb - lib/ldap/control.rb - lib/ldap/ldif.rb - extconf.rb - rbldap.h - win/winlber.h - win/winldap.h - conn.c - sslconn.c - entry.c - clientauth.c - ldap.c - mod.c - saslconn.c - misc.c - win/wldap32.def homepage: http://ruby-ldap.sourceforge.net/ licenses: [] metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: ruby-ldap rubygems_version: 2.0.7 signing_key: specification_version: 4 summary: Ruby/LDAP is an extension module for Ruby test_files: [] ruby-ldap-0.9.16/test/0000755000004100000410000000000012260553634014523 5ustar www-datawww-dataruby-ldap-0.9.16/test/add.rb0000644000004100000410000000164712260553634015610 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" conn = LDAP::Conn.new($HOST, $PORT) conn.bind('cn=root, dc=localhost, dc=localdomain','secret'){ conn.perror("bind") entry1 = [ LDAP.mod(LDAP::LDAP_MOD_ADD, 'objectclass', ['top', 'domain']), LDAP.mod(LDAP::LDAP_MOD_ADD, 'o', ['TTSKY.NET']), LDAP.mod(LDAP::LDAP_MOD_ADD, 'dc', ['localhost']), ] entry2 = [ LDAP.mod(LDAP::LDAP_MOD_ADD, 'objectclass', ['top', 'person']), LDAP.mod(LDAP::LDAP_MOD_ADD, 'cn', ['Takaaki Tateishi']), LDAP.mod(LDAP::LDAP_MOD_ADD | LDAP::LDAP_MOD_BVALUES, 'sn', ['ttate','Tateishi', "zero\000zero"]), ] begin conn.add("dc=localhost, dc=localdomain", entry1) conn.add("cn=Takaaki Tateishi, dc=localhost, dc=localdomain", entry2) rescue LDAP::ResultError conn.perror("add") exit end conn.perror("add") } ruby-ldap-0.9.16/test/add3.rb0000644000004100000410000000147212260553634015667 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" $KCODE = "UTF8" conn = LDAP::Conn.new($HOST, $PORT) conn.bind('cn=root, dc=localhost, dc=localdomain','secret'){ conn.perror("bind") entry1 = { 'objectclass' => ['top', 'person'], 'cn' => ['立石 孝彰'], 'sn' => ['孝彰'], } entry2 = { 'objectclass' => ['top', 'person'], 'cn' => ['たていし たかあき'], 'sn' => ['たていし','たかあき'], } begin conn.add("cn=#{entry1['cn'][0]}, dc=localhost, dc=localdomain", entry1) conn.add("cn=#{entry2['cn'][0]}, dc=localhost, dc=localdomain", entry2) rescue LDAP::ResultError conn.perror("add") exit end conn.perror("add") } ruby-ldap-0.9.16/test/search2.rb0000644000004100000410000000137312260553634016403 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" sorter = proc{|s1,s2| print("sorter: #{s1} <=> #{s2}\n") s1<=>s2 } LDAP::Conn.new($HOST, $PORT).bind{|conn| conn.perror("bind") sub = nil conn.search("dc=localhost, dc=localdomain", LDAP::LDAP_SCOPE_SUBTREE, "(objectclass=*)", nil, false, 0, 0, "sn", sorter){|e| dn = e.dn print("# #{LDAP.dn2ufn(dn)}\n") print("dn: #{dn}\n") e.attrs.each{|attr| print("#{attr}: #{e.vals(attr).join(', ')}\n") } print("\n") sub = e if !sub } begin sub.dn rescue LDAP::InvalidEntryError => e $stderr.print("#{e.to_s}.\n", "This exception is expected.\n") end } ruby-ldap-0.9.16/test/bind-sasl.rb0000644000004100000410000000055612260553634016732 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" cred = "secret" conn = LDAP::Conn.new($HOST, $PORT) v = conn.get_option(LDAP::LDAP_OPT_PROTOCOL_VERSION) printf("protocol version = #{v}\n") conn.sasl_bind(nil, LDAP::LDAP_SASL_SIMPLE, cred){ conn.perror("bind") } ruby-ldap-0.9.16/test/tc_schema.rb0000755000004100000410000000166512260553634017011 0ustar www-datawww-data# $Id: tc_schema.rb,v 1.4 2005/03/13 10:11:41 ianmacd Exp $ # # A suite of unit tests for testing Ruby/LDAP schema functionality. require 'ldap' require 'ldap/schema' require 'test/unit' require './setup' class TC_SchemaTest < TC_LDAPTest def test_schema schema = @@conn.schema assert_instance_of( LDAP::Schema, schema ) assert( schema.key?( 'attributeTypes' ) ) assert( schema.key?( 'ldapSyntaxes' ) ) assert( schema.key?( 'matchingRules' ) ) assert( schema.key?( 'matchingRuleUse' ) ) assert( schema.key?( 'objectClasses' ) ) end def test_root_dse root_dse = @@conn.root_dse[0] assert( root_dse.key?( 'subschemaSubentry' ) ) assert( root_dse.key?( 'namingContexts' ) ) assert( root_dse.key?( 'supportedSASLMechanisms' ) ) assert( root_dse.key?( 'supportedControl' ) ) assert( root_dse.key?( 'supportedExtension' ) ) assert( root_dse.key?( 'supportedLDAPVersion' ) ) end end ruby-ldap-0.9.16/test/ext.rb0000644000004100000410000000216012260553634015647 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" conn = LDAP::Conn.new($HOST, $PORT) conn.bind('cn=root, dc=localhost, dc=localdomain','secret'){ conn.perror("bind") begin (1..200).each{|i| entry = { 'objectclass' => ['top', 'person'], 'cn' => ["User #{i}"], 'sn' => ["user#{i}"], } conn.add("cn=User #{i}, dc=localhost, dc=localdomain", entry) } rescue LDAP::ResultError conn.perror("add") exit(1) end conn.perror("add") if( !defined?(conn.search_ext) ) exit(0) end users = [] begin conn.search_ext("dc=localhost, dc=localdomain", LDAP::LDAP_SCOPE_SUBTREE, "(&(objectclass=*)(cn=User*))", nil, false, # attrs, attrsonly nil, nil, # serverctrls, clientctrls 0, 0, # sec, usec 100){|e| # sizelimit users.push(e.vals("sn")) } rescue LDAP::ResultError conn.perror("search_ext") if( conn.err == LDAP::LDAP_SIZELIMIT_EXCEEDED ) exit(0) else exit(1) end end } ruby-ldap-0.9.16/test/add2.rb0000644000004100000410000000140712260553634015664 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" conn = LDAP::Conn.new($HOST, $PORT) conn.bind('cn=root, dc=localhost, dc=localdomain','secret'){ conn.perror("bind") entry1 = { 'objectclass' => ['top', 'person'], 'cn' => ['Tatsuya Kawai'], 'sn' => ['kawai'], } entry2 = { 'objectclass' => ['top', 'person'], 'cn' => ['Mio Tanaka'], 'sn' => ['mit','mio'], } begin conn.add("cn=#{entry1['cn'][0]}, dc=localhost, dc=localdomain", entry1) conn.add("cn=#{entry2['cn'][0]}, dc=localhost, dc=localdomain", entry2) rescue LDAP::ResultError conn.perror("add") exit end conn.perror("add") } ruby-ldap-0.9.16/test/tc_ldif.rb0000755000004100000410000001323212260553634016460 0ustar www-datawww-data# $Id: tc_ldif.rb,v 1.5 2005/02/26 01:42:27 ianmacd Exp $ # # A suite of unit tests for testing Ruby/LDAP LDIF functionality. require 'ldap' require 'ldap/ldif' require 'ldap/control' require 'test/unit' class TC_LDIFTest < Test::Unit::TestCase include LDAP::LDIF def test_version_entry ldif = File.open( 'data/ldif1.txt' ) { |f| f.readlines } entry = nil assert_nothing_raised { entry = LDAP::LDIF.parse_entry( ldif ) } assert_instance_of( LDAP::Record, entry ) assert_instance_of( String, entry.dn ) assert_instance_of( Array, entry.attrs['objectclass'] ) assert( entry.attrs['objectclass'].length > 1 ) end def test_bad_version_entry ldif = File.open( 'data/ldif2.txt' ) { |f| f.readlines } assert_raise( LDIFError ) { LDAP::LDIF.parse_entry( ldif ) } end def test_no_version_entry ldif = File.open( 'data/ldif3.txt' ) { |f| f.readlines } assert_nothing_raised { LDAP::LDIF.parse_entry( ldif ) } end def test_file entries = LDAP::LDIF.parse_file( 'data/ldif4.txt' ) assert_instance_of( Array, entries ) assert_instance_of( Hash, entries[0].attrs ) assert_not_equal( {}, entries[0].attrs ) end def test_folded_attribute_entry ldif = File.open( 'data/ldif5.txt' ) { |f| f.readlines } entry = nil assert_nothing_raised { entry = LDAP::LDIF.parse_entry( ldif ) } assert_no_match( /\n/, entry.attrs['description'][0] ) assert( entry.attrs['description'][0].length > LDAP::LDIF::LINE_LENGTH ) end def test_base64_value_entry ldif = File.open( 'data/ldif6.txt' ) { |f| f.readlines } entry = LDAP::LDIF.parse_entry( ldif ) assert_match( /\r/, entry.attrs['description'][0] ) end def test_utf8_file entries = LDAP::LDIF.parse_file( 'data/ldif7.txt' ) assert_instance_of( Array, entries ) assert_instance_of( Hash, entries[0].attrs ) assert_not_equal( {}, entries[0].attrs ) end def test_external_file_entry ldif = File.open( 'data/ldif8.txt' ) { |f| f.readlines } entry = LDAP::LDIF.parse_entry( ldif ) assert( entry.attrs['jpegphoto'][0].size > 1024 ) end def test_change_records_file entries = LDAP::LDIF.parse_file( 'data/ldif9.txt' ) assert_instance_of( Array, entries ) assert_instance_of( Hash, entries[0].attrs ) assert_not_equal( {}, entries[0].attrs ) end def test_bad_line_entry ldif = File.open( 'data/ldif10.txt' ) { |f| f.readlines } assert_raise( LDIFError ) { LDAP::LDIF.parse_entry( ldif ) } end def test_bad_attr_entry ldif = File.open( 'data/ldif11.txt' ) { |f| f.readlines } assert_raise( LDIFError ) { LDAP::LDIF.parse_entry( ldif ) } end def test_change_record_binary_replace_entry ldif = File.open( 'data/ldif12.txt' ) { |f| f.readlines } entry = LDAP::LDIF.parse_entry( ldif ) assert( entry.mods.keys.include?( LDAP::LDAP_MOD_REPLACE | LDAP::LDAP_MOD_BVALUES ) ) end def test_change_record_control ldif = File.open( 'data/ldif13.txt' ) { |f| f.readlines } entry = LDAP::LDIF.parse_entry( ldif ) assert_instance_of( LDAP::Control, entry.controls[0] ) assert_equal( entry.controls[0].oid, '1.2.840.113556.1.4.805' ) assert( entry.controls[0].iscritical ) assert_nil( entry.controls[0].value ) end def test_change_record_control2 ldif = File.open( 'data/ldif14.txt' ) { |f| f.readlines } entry = LDAP::LDIF.parse_entry( ldif ) assert_instance_of( LDAP::Control, entry.controls[0] ) assert_equal( entry.controls[0].oid, '1.2.3.4' ) assert_equal( entry.controls[0].iscritical, false ) assert_not_nil( entry.controls[0].value ) end def test_mod_to_ldif mod = LDAP.mod( LDAP::LDAP_MOD_ADD | LDAP::LDAP_MOD_BVALUES, 'mailRoutingAddress', ['a', 'b'] ) assert_instance_of( LDAP::LDIF::Mod, mod.to_ldif( 'uid=foo,dc=example,dc=com' ) ) assert_equal( < 'localhost', :port => '389', :scope => 'base', :filter => '(objectclass=*)', :key_pw => '' } optparse = OptionParser.new do |opts| opts.on("-P", "--certpath [CERTFILE]", "cert8 path") do |cp| options[:cp] = cp end opts.on("-N", "--certname [CERTNAME]", "certificate name") do |opt| options[:cn] = opt end opts.on("-W", "--keypassword PASSWORD", "key password") do |opt| options[:key_pw] = opt end opts.on("-h", "--host HOST", "server hostname") do |host| options[:host] = host end opts.on("-p", "--port PORT", "server port") do |opt| options[:port] = opt end opts.on("-b", "--base [BASE]", "search base") do |opt| options[:base] = opt end opts.on("-s", "--scope SCOPE", "search scope") do |opt| options[:scope] = opt end opts.on("-f", "--filter FILTER", "search filter") do |opt| options[:filter] = opt end opts.on("-a", "--attributes ATTRS", "attrs to return") do |opt| options[:attrs] = opt.split(/ *, */) end opts.on("--help") do |opt| puts opts exit 0 end end optparse.parse! required_keys = [:cp, :cn, :base] if (required_keys - options.keys).length > 0 puts "Some options are missing." puts optparse exit 1 end options[:scope] = case options[:scope] when "sub" LDAP::LDAP_SCOPE_SUBTREE when "one" LDAP::LDAP_SCOPE_ONELEVEL else LDAP::LDAP_SCOPE_BASE end raise ArgumentError.new("cert file's missing") unless (File.exists? options[:cp]) #Signal.trap("INT") { puts("INT"); exit(2); } # Connect conn = LDAP::SSLAuthConn.new(options[:host], options[:port].to_i, true, File.expand_path(options[:cp]), options[:cn], options[:key_pw]) conn.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3) # oid = '2.16.840.1.113730.3.4.15' # get bound DN # bindctls = [LDAP::Control.new(oid, "", false)] # pass bindctls as argument to bind() begin conn.bind results = {} conn.search(options[:base], options[:scope], options[:filter], options[:attrs], false, 10) do |entry| results[entry.dn] = entry.to_hash end pp results rescue LDAP::ResultError => e puts "error: #{e.to_s}" end exit 0 ruby-ldap-0.9.16/test/modrdn.rb0000644000004100000410000000107212260553634016333 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" conn = LDAP::Conn.new($HOST, $PORT) begin conn.bind('cn=root, dc=localhost, dc=localdomain','seret') rescue LDAP::ResultError => e $stderr.print("#{e.inspect} ... expected.\n") conn.bind('cn=root, dc=localhost, dc=localdomain','secret'){ conn.perror("bind") conn.modrdn("cn=Takaaki Tateishi, dc=localhost, dc=localdomain", "cn=Takaaki-Tateishi", true) conn.perror("modrdn") } exit(0) end exit(1) ruby-ldap-0.9.16/test/search3.rb0000644000004100000410000000104212260553634016375 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" $KCODE = "UTF8" conn = LDAP::Conn.new($HOST, $PORT) conn.perror("bind") conn.bind{ # search2 returns an array of hash print("search2 without a block:\n") conn.search2("dc=localhost, dc=localdomain", LDAP::LDAP_SCOPE_SUBTREE, "(objectclass=*)", nil, false, 0, 0).each{|ent| ent.each{|attr,vals| print("#{attr}: #{vals.join(', ')}\n") } print("\n") } GC.start() } ruby-ldap-0.9.16/test/subschema.rb0000644000004100000410000000067312260553634017030 0ustar www-datawww-data $test = File.dirname($0) require "#{$test}/conf" require "./ldap" require "#{$test}/../lib/ldap/schema" conn = LDAP::Conn.new($HOST, $PORT) conn.bind{ schema = conn.schema() p schema.must("person") p schema.attr("person", "MUST") p schema.may("person") p schema.attr("person", "MAY") p schema.sup("person") p schema.attr("person", "SUP") schema.each{|key,vals| vals.each{|val| print("#{key}: #{val}\n") } } } ruby-ldap-0.9.16/test/bind.rb0000644000004100000410000000160312260553634015764 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" conn = LDAP::Conn.new($HOST, $PORT) conn.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3) conn.bind{ conn.perror("bind") if( defined?(LDAP::LDAP_OPT_HOST_NAME) && defined?(LDAP::LDAP_OPT_PROTOCOL_VERSION) && defined?(LDAP::LDAP_OPT_API_INFO) ) # checking for LDAPv3 API host = conn.get_option(LDAP::LDAP_OPT_HOST_NAME) proto = conn.get_option(LDAP::LDAP_OPT_PROTOCOL_VERSION) begin info = conn.get_option(LDAP::LDAP_OPT_API_INFO) rescue LDAP::Error info = nil end print("host = #{host}, proto = #{proto}\n", "info.protocol_version = #{info.protocol_version}\n") end } begin conn.bind rescue LDAP::InvalidDataError $ok = true end if( ! $ok ) raise(RuntimeError, "multiple bind calls") end ruby-ldap-0.9.16/test/misc2.rb0000644000004100000410000000156112260553634016070 0ustar www-datawww-data# -*- ruby -*- $test = File.dirname($0) require "#{$test}/conf" require "./ldap" def add_ou(agency) #creates an organizational unit and places an agency inside begin entry = { 'objectclass' => ['organizationalUnit'], 'ou' => [agency] } @ldap_conn.add("ou=#{entry['ou'][0]}, dc=localhost, dc=localdomain", entry) return(true) rescue LDAP::ResultError => error return(false) end end def delete_ou(agency) #removes an agency organizational unit begin @ldap_conn.delete("ou=#{agency}, dc=localhost, dc=localdomain") return(true) rescue LDAP::ResultError => error return(false) end end @ldap_conn = LDAP::Conn.new($HOST, $PORT) @ldap_conn.bind("cn=root, dc=localhost, dc=localdomain", 'secret') p LDAP::VERSION (1..100).each do |count| p count p add_ou("an_agency") p delete_ou("an_agency") GC.start end ruby-ldap-0.9.16/test/bind-ssl.rb0000644000004100000410000000116512260553634016566 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" case LDAP::LDAP_VENDOR_NAME when /^OpenLDAP/i # true means we use start_tls extension. conn = LDAP::SSLConn.new($HOST, $PORT, true) when /^Netscape/i conn = LDAP::SSLConn.new($HOST, $SSLPORT, false, File.expand_path("~/.netscape/cert7.db")) conn.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3) else raise(RuntimeError, "unknown vendor") end v = conn.get_option(LDAP::LDAP_OPT_PROTOCOL_VERSION) printf("protocol version = #{v}\n") conn.bind{ conn.perror("bind") } ruby-ldap-0.9.16/test/delete.rb0000644000004100000410000000054712260553634016320 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" conn = LDAP::Conn.new($HOST, $PORT) conn.bind('cn=root, dc=localhost, dc=localdomain','secret'){ conn.perror("bind") conn.delete("cn=Takaaki-Tateishi, dc=localhost, dc=localdomain") conn.perror("delete") } ruby-ldap-0.9.16/test/setup.rb0000755000004100000410000000151212260553634016212 0ustar www-datawww-data# $Id: setup.rb,v 1.3 2005/03/13 10:10:56 ianmacd Exp $ # # Basic set-up for performing LDAP unit tests. require 'ldap' require 'ldap/schema' require 'test/unit' class TC_LDAPTest < Test::Unit::TestCase @@conn = nil # Get the LDAP host and base DN from /etc/ldap.conf. def setup unless @@conn && @@conn.bound? File.open( '/etc/ldap.conf' ) do |f| while line = f.gets if line =~ /^host\s+(\S+)$/ @@host = $1 break elsif line =~ /^base\s+(\S+)$/ @@base = $1 break end end end @@conn = LDAP::Conn.new( @@host ) @@conn.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 ) @@conn.bind @@root_dse = @@conn.root_dse[0] @@naming_context = @@root_dse['namingContexts'][0] end end undef_method :default_test end ruby-ldap-0.9.16/test/ts_ldap.rb0000644000004100000410000000025412260553634016477 0ustar www-datawww-data# $Id: ts_ldap.rb,v 1.1 2005/03/12 09:44:11 ianmacd Exp $ # # Test suite runner for Ruby/LDAP. require 'tc_conn' require 'tc_schema' require 'tc_search' require 'tc_ldif' ruby-ldap-0.9.16/test/search.rb0000644000004100000410000000065712260553634016325 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" LDAP::Conn.new($HOST, $PORT).bind{|conn| conn.perror("bind") begin conn.search("dc=localhost, dc=localdomain", LDAP::LDAP_SCOPE_SUBTREE, "(objectclass=*)"){|e| p e.vals("cn") p e.to_hash() } rescue LDAP::ResultError => msg $stderr.print(msg) end } ruby-ldap-0.9.16/test/tc_search.rb0000755000004100000410000000675312260553634017021 0ustar www-datawww-data# $Id: tc_search.rb,v 1.4 2006/02/12 19:55:59 ianmacd Exp $ # # A suite of unit tests for testing Ruby/LDAP search functionality. require 'ldap' require 'ldap/control' require 'test/unit' require './setup' class TC_SearchTest < TC_LDAPTest # Ensure that giving an incorrect attribute argument raises an exception # and that passing a string instead of an array is treated as a single # element array. # def test_attrs assert_raise( TypeError ) do @@conn.search( @@naming_context, LDAP::LDAP_SCOPE_ONELEVEL, '(objectClass=*)', false ) end @@conn.search( @@naming_context, LDAP::LDAP_SCOPE_ONELEVEL, '(objectClass=*)', [], true ) do |x| assert_nil( x['objectClass'] ) break end @@conn.search( @@naming_context, LDAP::LDAP_SCOPE_ONELEVEL, '(objectClass=*)', 'objectClass' ) do |x| x = x.to_hash x.delete( 'dn' ) assert( x.to_hash.keys == [ 'objectClass' ] ) break end end # Ensure that we can sort on a given attribute. # def test_sort_attr ou = [] @@conn.search( @@naming_context, LDAP::LDAP_SCOPE_ONELEVEL, '(ou=*)' ) do |x| ou << x['ou'] end ou.flatten! sorted_ou = [] @@conn.search( @@naming_context, LDAP::LDAP_SCOPE_ONELEVEL, '(ou=*)', nil, nil, 0, 0, 'ou' ) do |x| sorted_ou << x['ou'] end sorted_ou.flatten! assert_not_equal( ou, sorted_ou ) assert_equal( ou.sort, sorted_ou ) end # Ensure that we can pass a proc object to use for sorting. # def test_sort_proc ct = [] @@conn.search( @@naming_context, LDAP::LDAP_SCOPE_ONELEVEL, '(objectClass=*)', [ 'createTimestamp' ] ) do |x| ct << x['createTimestamp'] end ct.flatten! sorted_ct = [] s_proc = proc { |a,b| b <=> a } @@conn.search( @@naming_context, LDAP::LDAP_SCOPE_ONELEVEL, '(objectClass=*)', [ 'createTimestamp' ], nil, 0, 0, 'createTimestamp', s_proc ) do |x| sorted_ct << x['createTimestamp'] end sorted_ct.flatten! assert_not_equal( ct, sorted_ct ) assert_equal( ct.sort( &s_proc ), sorted_ct ) end # Ensure that the paged results control works properly. # def test_paged_results total = 0 page_size = 1 cookie = '' loop do ber_string = LDAP::Control.encode( page_size, cookie ) ctrl = LDAP::Control.new( LDAP::LDAP_CONTROL_PAGEDRESULTS, ber_string, true ) @@conn.set_option( LDAP::LDAP_OPT_SERVER_CONTROLS, [ ctrl ] ) this_page = nil assert_nothing_raised do begin this_page = @@conn.search2( @@naming_context, LDAP::LDAP_SCOPE_ONELEVEL, '(objectclass=*)' ) rescue LDAP::ResultError @@conn = nil raise end end total += this_page.size assert_equal( page_size, this_page.size ) @@conn.controls.each do |c| if c.oid == LDAP::LDAP_CONTROL_PAGEDRESULTS ctrl = c break end end assert_equal( ctrl.oid, LDAP::LDAP_CONTROL_PAGEDRESULTS ) fetched_size, cookie = ctrl.decode page_size = fetched_size if fetched_size.to_i > 0 break if cookie.empty? end # Reset connection. @@conn = nil setup unpaged = @@conn.search2( @@naming_context, LDAP::LDAP_SCOPE_ONELEVEL, '(objectclass=*)' ) # Does the total number of results match the equivalent unpaged search? # This has a race condition, but we assume the number of top-level OUs is # more or less static. :-) assert_equal( total, unpaged.size ) end end ruby-ldap-0.9.16/test/compare.rb0000644000004100000410000000056612260553634016505 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" LDAP::Conn.new($HOST, $PORT).bind{|conn| conn.perror("bind") begin conn.compare("cn=Takaaki Tateishi, dc=localhost, dc=localdomain", "cn", "Takaaki Tateishi") rescue LDAP::ResultError exit(0) end exit(1) } ruby-ldap-0.9.16/test/bind-ldaps.rb0000644000004100000410000000116512260553634017070 0ustar www-datawww-data# -*- ruby -*- # This file is a part of test scripts of LDAP extension module. $test = File.dirname($0) require "#{$test}/conf" require "./ldap" case LDAP::LDAP_VENDOR_NAME when /^OpenLDAP/i # false means we use SSL connection. conn = LDAP::SSLConn.new($HOST, $SSLPORT, false) when /^Netscape/i conn = LDAP::SSLConn.new($HOST, $SSLPORT, false, File.expand_path("~/.netscape/cert7.db")) conn.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3) else raise(RuntimeError, "unknown vendor") end v = conn.get_option(LDAP::LDAP_OPT_PROTOCOL_VERSION) printf("protocol version = #{v}\n") conn.bind{ conn.perror("bind") } ruby-ldap-0.9.16/test/conf.rb0000644000004100000410000000032712260553634015777 0ustar www-datawww-data# -*- ruby -*- require './ldap' $HOST = 'localhost' begin $PORT = ARGV[0].to_i || LDAP::LDAP_PORT $SSLPORT = ARGV[1].to_i || LDAP::LDAPS_PORT rescue $PORT = LDAP::LDAP_PORT $SSLPORT = LDAP::LDAPS_PORT end ruby-ldap-0.9.16/test/misc1.rb0000644000004100000410000000171612260553634016071 0ustar www-datawww-data# -*- ruby -*- $test = File.dirname($0) require "#{$test}/conf" require "./ldap" def admin_bind @ldap_conn.bind("cn=root, dc=localhost, dc=localdomain", 'secret') end #test method goes here def add_ou(agency) #creates an organizational unit and places an agency inside begin entry = { 'objectclass' => ['organizationalUnit'], 'ou' => [agency] } admin_bind.add("ou=#{entry['ou'][0]}, dc=localhost, dc=localdomain", entry) return(true) rescue LDAP::ResultError => error return(false) end end def delete_ou(agency) #removes an agency organizational unit begin admin_bind.delete("ou=#{agency}, dc=localhost, dc=localdomain") return(true) rescue LDAP::ResultError => error return(false) end end @ldap_conn = LDAP::Conn.new($HOST, $PORT) p LDAP::VERSION begin (1..1000).each do |count| p count p add_ou("an_agency") p delete_ou("an_agency") end rescue LDAP::Error exit(0) end exit(1) ruby-ldap-0.9.16/entry.c0000644000004100000410000001136212260553634015054 0ustar www-datawww-data/* * entry.c * $Id: entry.c,v 1.13 2005/03/15 10:15:32 ianmacd Exp $ */ #include "ruby.h" #include "rbldap.h" VALUE rb_cLDAP_Entry; void rb_ldap_entry_free (RB_LDAPENTRY_DATA * edata) { xfree(edata); /* edata->msg is valid in a block given by each search operation */ /* ldap_msgfree should be called after ldap_search */ } VALUE rb_ldap_entry_new (LDAP * ldap, LDAPMessage * msg) { VALUE val; RB_LDAPENTRY_DATA *edata; val = Data_Make_Struct (rb_cLDAP_Entry, RB_LDAPENTRY_DATA, 0, rb_ldap_entry_free, edata); edata->ldap = ldap; edata->msg = msg; return val; } /* * call-seq: * entry.get_dn => String * entry.dn => String */ VALUE rb_ldap_entry_get_dn (VALUE self) { RB_LDAPENTRY_DATA *edata; char *cdn; VALUE dn; GET_LDAPENTRY_DATA (self, edata); cdn = ldap_get_dn (edata->ldap, edata->msg); if (cdn) { dn = rb_tainted_str_new2 (cdn); ldap_memfree (cdn); } else { dn = Qnil; } return dn; } /* * call-seq: * entry.get_values(attr) => Array of String * entry.vals(attr) => Array of String * entry[attr] => Array of String * * Return an array of all the values belonging to the attribute, +attr+, of * the entry. */ VALUE rb_ldap_entry_get_values (VALUE self, VALUE attr) { RB_LDAPENTRY_DATA *edata; char *c_attr; struct berval **c_vals; int i; int count; VALUE vals; GET_LDAPENTRY_DATA (self, edata); c_attr = StringValueCStr (attr); c_vals = ldap_get_values_len (edata->ldap, edata->msg, c_attr); if (c_vals) { vals = rb_ary_new (); count = ldap_count_values_len (c_vals); for (i = 0; i < count; i++) { VALUE str; str = rb_tainted_str_new (c_vals[i]->bv_val, c_vals[i]->bv_len); rb_ary_push (vals, str); } ldap_value_free_len (c_vals); } else { vals = Qnil; } return vals; } /* * call-seq: * entry.get_attributes => Array of String * entry.attrs => Array of String * * Return an array of all the attributes belonging to the entry. */ VALUE rb_ldap_entry_get_attributes (VALUE self) { RB_LDAPENTRY_DATA *edata; VALUE vals; char *attr; BerElement *ber = NULL; GET_LDAPENTRY_DATA (self, edata); vals = rb_ary_new (); for (attr = ldap_first_attribute (edata->ldap, edata->msg, &ber); attr != NULL; attr = ldap_next_attribute (edata->ldap, edata->msg, ber)) { rb_ary_push (vals, rb_tainted_str_new2 (attr)); ldap_memfree(attr); } #if !defined(USE_OPENLDAP1) if( ber != NULL ){ ber_free(ber, 0); } #endif return vals; } /* * call-seq: * entry.to_hash => Hash * * Convert the entry to a hash. */ VALUE rb_ldap_entry_to_hash (VALUE self) { VALUE attrs = rb_ldap_entry_get_attributes (self); VALUE hash = rb_hash_new (); VALUE attr, vals; int i; Check_Type (attrs, T_ARRAY); rb_hash_aset (hash, rb_tainted_str_new2 ("dn"), rb_ary_new3 (1, rb_ldap_entry_get_dn (self))); for (i = 0; i < RARRAY_LEN (attrs); i++) { attr = rb_ary_entry (attrs, i); vals = rb_ldap_entry_get_values (self, attr); rb_hash_aset (hash, attr, vals); } return hash; } /* * call-seq: * entry.inspect => String * * Produce a concise representation of the entry. */ VALUE rb_ldap_entry_inspect (VALUE self) { VALUE str; const char *c; c = rb_obj_classname (self); str = rb_str_new (0, strlen (c) + 10 + 16 + 1); /* 10:tags 16:addr 1:nul */ sprintf (RSTRING_PTR (str), "#<%s:0x%lx\n", c, self); #if RUBY_VERSION_CODE < 190 RSTRING(str)->len = strlen (RSTRING_PTR (str)); #else rb_str_set_len(str, strlen (RSTRING_PTR (str))); #endif rb_str_concat (str, rb_inspect (rb_ldap_entry_to_hash (self))); rb_str_cat2 (str, ">"); return str; } /* Document-class: LDAP::Entry * * These methods can be used to probe the entries returned by LDAP searches. */ void Init_ldap_entry () { rb_cLDAP_Entry = rb_define_class_under (rb_mLDAP, "Entry", rb_cObject); rb_define_const (rb_mLDAP, "Message", rb_cLDAP_Entry); /* for compatibility */ rb_undef_method (CLASS_OF (rb_cLDAP_Entry), "new"); rb_undef_alloc_func (rb_cLDAP_Entry); rb_ldap_entry_define_method ("get_dn", rb_ldap_entry_get_dn, 0); rb_ldap_entry_define_method ("get_values", rb_ldap_entry_get_values, 1); rb_ldap_entry_define_method ("get_attributes", rb_ldap_entry_get_attributes, 0); rb_alias (rb_cLDAP_Entry, rb_intern ("dn"), rb_intern ("get_dn")); rb_alias (rb_cLDAP_Entry, rb_intern ("vals"), rb_intern ("get_values")); rb_alias (rb_cLDAP_Entry, rb_intern ("[]"), rb_intern ("get_values")); rb_alias (rb_cLDAP_Entry, rb_intern ("attrs"), rb_intern ("get_attributes")); rb_ldap_entry_define_method ("to_hash", rb_ldap_entry_to_hash, 0); rb_ldap_entry_define_method ("inspect", rb_ldap_entry_inspect, 0); } ruby-ldap-0.9.16/misc.c0000644000004100000410000002602712260553634014652 0ustar www-datawww-data/* -*- C -*- * $Id: misc.c,v 1.11 2006/07/03 22:54:52 ianmacd Exp $ */ #include "ruby.h" #include "rbldap.h" VALUE rb_sLDAP_APIInfo; VALUE rb_cLDAP_Control; #ifdef LDAP_OPT_API_INFO VALUE rb_ldap_apiinfo_new (LDAPAPIInfo * info) { VALUE info_version, api_version, protocol_version; VALUE extensions, vendor_name, vendor_version; int i; info_version = INT2NUM (info->ldapai_info_version); api_version = INT2NUM (info->ldapai_api_version); protocol_version = INT2NUM (info->ldapai_protocol_version); vendor_version = INT2NUM (info->ldapai_vendor_version); vendor_name = rb_tainted_str_new2 (info->ldapai_vendor_name); extensions = rb_ary_new (); for (i = 0; info->ldapai_extensions[i]; i++) { rb_ary_push (extensions, rb_tainted_str_new2 (info->ldapai_extensions[i])); } return rb_struct_new (rb_sLDAP_APIInfo, info_version, api_version, protocol_version, extensions, vendor_name, vendor_version, 0); } LDAPAPIInfo * rb_ldap_get_apiinfo (VALUE data) { LDAPAPIInfo *info; VALUE r_extensions; int len, i; char **c_extensions; if (data == Qnil) return NULL; info = ALLOC_N (LDAPAPIInfo, 1); info->ldapai_info_version = FIX2INT (rb_struct_getmember (data, rb_intern ("info_version"))); info->ldapai_api_version = FIX2INT (rb_struct_getmember (data, rb_intern ("api_version"))); info->ldapai_protocol_version = FIX2INT (rb_struct_getmember (data, rb_intern ("protocol_version"))); r_extensions = rb_struct_getmember (data, rb_intern ("extensions")); len = RARRAY_LEN (r_extensions); c_extensions = ALLOCA_N (char *, len); for (i = 0; i <= len - 1; i++) { VALUE str = RARRAY_PTR (r_extensions)[i]; RB_LDAP_SET_STR (c_extensions[i], str); } info->ldapai_extensions = c_extensions; RB_LDAP_SET_STR (info->ldapai_vendor_name, rb_struct_getmember (data, rb_intern ("vendor_name"))); info->ldapai_vendor_version = FIX2INT (rb_struct_getmember (data, rb_intern ("vendor_version"))); return info; } #endif /* LDAP_OPT_API_INFO */ #ifdef HAVE_LDAPCONTROL static void rb_ldap_control_free (LDAPControl * ctl) { if (ctl) { if (ctl->ldctl_value.bv_val) xfree (ctl->ldctl_value.bv_val); if (ctl->ldctl_oid) xfree (ctl->ldctl_oid); xfree (ctl); } } VALUE rb_ldap_control_new (LDAPControl * ctl) { if (!ctl) return Qnil; else return Data_Wrap_Struct (rb_cLDAP_Control, 0, rb_ldap_control_free, ctl); } /* Identical to rb_ldap_control_new, but does not define a routine with which to free memory. This should be called only by rb_ldap_parse_result(). */ VALUE rb_ldap_control_new2 (LDAPControl * ctl) { if (!ctl) return Qnil; else return Data_Wrap_Struct (rb_cLDAP_Control, 0, 0, ctl); } /* This is called by #initialize_copy and is using for duping/cloning. */ VALUE rb_ldap_control_copy (VALUE copy, VALUE orig) { LDAPControl *orig_ctl, *copy_ctl; Data_Get_Struct (orig, LDAPControl, orig_ctl); Data_Get_Struct (copy, LDAPControl, copy_ctl); memcpy (copy_ctl, orig_ctl, (size_t) sizeof (LDAPControl)); return copy; } static VALUE rb_ldap_control_s_allocate (VALUE klass) { LDAPControl *ctl; ctl = ALLOC_N (LDAPControl, 1); ctl->ldctl_value.bv_val = NULL; ctl->ldctl_value.bv_len = 0; ctl->ldctl_oid = NULL; ctl->ldctl_iscritical = 0; return Data_Wrap_Struct (klass, 0, rb_ldap_control_free, ctl); } #if RUBY_VERSION_CODE < 170 static VALUE rb_ldap_control_s_new (int argc, VALUE argv[], VALUE klass) { VALUE obj; obj = rb_ldap_control_s_allocate (klass); rb_obj_call_init (obj, argc, argv); return obj; } #endif static VALUE rb_ldap_control_set_value (VALUE self, VALUE val) { LDAPControl *ctl; Data_Get_Struct (self, LDAPControl, ctl); if (ctl->ldctl_value.bv_val) free (ctl->ldctl_value.bv_val); if (val == Qnil) { ctl->ldctl_value.bv_val = NULL; ctl->ldctl_value.bv_len = 0; } else { RB_LDAP_SET_STR (ctl->ldctl_value.bv_val, val); ctl->ldctl_value.bv_len = RSTRING_LEN (val); } return val; } static VALUE rb_ldap_control_get_value (VALUE self) { LDAPControl *ctl; VALUE val; Data_Get_Struct (self, LDAPControl, ctl); if (ctl->ldctl_value.bv_len == 0 || ctl->ldctl_value.bv_val == NULL) { val = Qnil; } else { val = rb_tainted_str_new (ctl->ldctl_value.bv_val, ctl->ldctl_value.bv_len); } return val; } /* * Document-method: value * * call-seq: * ctrl.value => String or nil * * Return the value of the control. */ /* * Document-method: value= * * call-seq: * ctrl.value=(val) => val * * Set the value of the control. */ static VALUE rb_ldap_control_value (int argc, VALUE argv[], VALUE self) { VALUE val; if (rb_scan_args (argc, argv, "01", &val) == 1) val = rb_ldap_control_set_value (self, val); else val = rb_ldap_control_get_value (self); return val; } static VALUE rb_ldap_control_set_oid (VALUE self, VALUE val) { LDAPControl *ctl; Data_Get_Struct (self, LDAPControl, ctl); if (ctl->ldctl_oid) free (ctl->ldctl_oid); if (val == Qnil) { ctl->ldctl_oid = NULL; } else { RB_LDAP_SET_STR (ctl->ldctl_oid, val); } return val; } static VALUE rb_ldap_control_get_oid (VALUE self) { LDAPControl *ctl; VALUE val; Data_Get_Struct (self, LDAPControl, ctl); if (ctl->ldctl_oid == NULL) { val = Qnil; } else { val = rb_tainted_str_new2 (ctl->ldctl_oid); } return val; } /* * Document-method: oid * * call-seq: * ctrl.oid => String or nil * * Return the OID of the control. */ /* * Document-method: oid= * * call-seq: * ctrl.oid=(oid) => oid * * Set the OID of the control. */ static VALUE rb_ldap_control_oid (int argc, VALUE argv[], VALUE self) { VALUE val; LDAPControl *ctl; Data_Get_Struct (self, LDAPControl, ctl); if (rb_scan_args (argc, argv, "01", &val) == 1) { val = rb_ldap_control_set_oid (self, val); } else { val = rb_ldap_control_get_oid (self); } return val; } static VALUE rb_ldap_control_set_critical (VALUE self, VALUE val) { LDAPControl *ctl; Data_Get_Struct (self, LDAPControl, ctl); ctl->ldctl_iscritical = (val == Qtrue) ? 1 : 0; return val; } static VALUE rb_ldap_control_get_critical (VALUE self) { LDAPControl *ctl; VALUE val; Data_Get_Struct (self, LDAPControl, ctl); val = ctl->ldctl_iscritical ? Qtrue : Qfalse; return val; } /* * Document-method: critical * * call-seq: * ctrl.critical => true or false * ctrl.critical? => true or false * ctrl.iscritical => true or false * * Return the criticality of the control. */ /* * Document-method: critical= * * call-seq: * ctrl.critical=(val) => val * ctrl.iscritical=(val) => val * * Set the criticality of the control. +val+ should be *true* or *false*. */ static VALUE rb_ldap_control_critical (int argc, VALUE argv[], VALUE self) { VALUE val; LDAPControl *ctl; Data_Get_Struct (self, LDAPControl, ctl); if (rb_scan_args (argc, argv, "01", &val) == 1) { val = rb_ldap_control_set_critical (self, val); } else { val = rb_ldap_control_get_critical (self); } return val; } /* * Document-method: new * * call-seq: * LDAP::Control.new(oid, value, criticality) => LDAP::Control * * Create a new LDAP::Control. +oid+ is the OID of the control, +value+ is the * value to be assigned to the control, and +criticality+ is the criticality * of the control, which should be *true* or *false*. */ static VALUE rb_ldap_control_initialize (int argc, VALUE argv[], VALUE self) { VALUE oid, value, critical; switch (rb_scan_args (argc, argv, "03", &oid, &value, &critical)) { case 3: rb_ldap_control_set_critical (self, critical); case 2: rb_ldap_control_set_value (self, value); case 1: rb_ldap_control_set_oid (self, oid); default: break; } return Qnil; } /* * call-seq: * ctrl.inspect => String * * Produce a concise representation of the control. */ static VALUE rb_ldap_control_inspect (VALUE self) { VALUE str; str = rb_tainted_str_new2 ("#<"); rb_str_cat2 (str, rb_class2name (CLASS_OF (self))); rb_str_cat2 (str, " oid="); rb_str_concat (str, rb_inspect (rb_ldap_control_get_oid (self))); rb_str_cat2 (str, " value="); rb_str_concat (str, rb_inspect (rb_ldap_control_get_value (self))); rb_str_cat2 (str, " iscritical="); rb_str_concat (str, rb_inspect (rb_ldap_control_get_critical (self))); rb_str_cat2 (str, ">"); return str; } VALUE rb_ldap_controls_new (LDAPControl ** ctrls) { int i; VALUE ary; if (!ctrls) return Qnil; ary = rb_ary_new (); for (i = 0; ctrls[i]; i++) rb_ary_push (ary, rb_ldap_control_new (ctrls[i])); return ary; } LDAPControl * rb_ldap_get_control (VALUE obj) { LDAPControl *ctl; if (obj == Qnil) { return NULL; } else { Data_Get_Struct (obj, LDAPControl, ctl); return ctl; } } LDAPControl ** rb_ldap_get_controls (VALUE data) { LDAPControl **ctls; int len, i; if (data == Qnil) return NULL; Check_Type (data, T_ARRAY); len = RARRAY_LEN (data); ctls = ALLOC_N (LDAPControl *, len + 1); for (i = 0; i < len; i++) { ctls[i] = rb_ldap_get_control (rb_ary_entry (data, i)); } ctls[len] = NULL; return ctls; } #endif /* Document-class: LDAP::Control * * Create, manipulate and inspect LDAP controls. */ void Init_ldap_misc () { rb_sLDAP_APIInfo = rb_struct_define ("APIInfo", "info_version", /* ldapai_xxxx */ "api_version", "protocol_version", "extensions", "vendor_name", "vendor_version", NULL); rb_define_const (rb_mLDAP, "APIInfo", rb_sLDAP_APIInfo); #ifdef HAVE_LDAPCONTROL rb_cLDAP_Control = rb_define_class_under (rb_mLDAP, "Control", rb_cObject); #if RUBY_VERSION_CODE < 170 rb_define_singleton_method (rb_cLDAP_Control, "new", rb_ldap_control_s_new, -1); #endif #if RUBY_VERSION_CODE >= 173 rb_define_alloc_func (rb_cLDAP_Control, rb_ldap_control_s_allocate); #else rb_define_singleton_method (rb_cLDAP_Control, "allocate", rb_ldap_control_s_allocate, 0); #endif rb_define_method (rb_cLDAP_Control, "initialize", rb_ldap_control_initialize, -1); rb_define_method (rb_cLDAP_Control, "initialize_copy", rb_ldap_control_copy, 1); rb_define_method (rb_cLDAP_Control, "inspect", rb_ldap_control_inspect, 0); rb_define_method (rb_cLDAP_Control, "oid", rb_ldap_control_oid, -1); rb_define_method (rb_cLDAP_Control, "oid=", rb_ldap_control_oid, -1); rb_define_method (rb_cLDAP_Control, "value", rb_ldap_control_value, -1); rb_define_method (rb_cLDAP_Control, "value=", rb_ldap_control_value, -1); rb_define_method (rb_cLDAP_Control, "critical?", rb_ldap_control_critical, -1); rb_define_method (rb_cLDAP_Control, "critical", rb_ldap_control_critical, -1); rb_define_method (rb_cLDAP_Control, "critical=", rb_ldap_control_critical, -1); rb_define_method (rb_cLDAP_Control, "iscritical", rb_ldap_control_critical, -1); rb_define_method (rb_cLDAP_Control, "iscritical=", rb_ldap_control_critical, -1); #endif } ruby-ldap-0.9.16/conn.c0000644000004100000410000013602512260553634014654 0ustar www-datawww-data/* * conn.c * $Id: conn.c,v 1.51 2006/08/01 00:07:53 ianmacd Exp $ */ #include "ruby.h" #include "rbldap.h" #if defined(HAVE_SYS_TIME_H) # include #endif #if defined(HAVE_UNISTD_H) # include #endif /* RDoc needs the following bogus code to find the parent module: * * rb_mLDAP = rb_define_module ("LDAP"); */ static VALUE rb_ldap_sort_obj = Qnil; extern VALUE rb_ldap_control_new2 (LDAPControl * ctl); extern VALUE rb_ldap_sslconn_initialize (int argc, VALUE argv[], VALUE self); extern VALUE rb_ldap_conn_rebind (VALUE self); VALUE rb_cLDAP_Conn; static void rb_ldap_conn_free (RB_LDAP_DATA * ldapdata) { if (ldapdata->ldap && ldapdata->bind) { ldap_unbind (ldapdata->ldap); }; xfree(ldapdata); }; static void rb_ldap_conn_mark (RB_LDAP_DATA * ldapdata) { /* empty */ }; VALUE rb_ldap_conn_new (VALUE klass, LDAP * cldap) { VALUE conn; RB_LDAP_DATA *ldapdata; conn = Data_Make_Struct (klass, RB_LDAP_DATA, rb_ldap_conn_mark, rb_ldap_conn_free, ldapdata); ldapdata->ldap = cldap; ldapdata->err = 0; ldapdata->bind = 0; return conn; }; VALUE rb_ldap_conn_s_allocate (VALUE klass) { return rb_ldap_conn_new (klass, (LDAP *) 0); } /* * call-seq: * LDAP::Conn.new(host='localhost', port=LDAP_PORT) => LDAP::Conn * * Return a new LDAP::Conn connection to the server, +host+, on port +port+. */ VALUE rb_ldap_conn_initialize (int argc, VALUE argv[], VALUE self) { LDAP *cldap; char *chost; int cport; int was_verbose = Qfalse; RB_LDAP_DATA *ldapdata; VALUE host, port; Data_Get_Struct (self, RB_LDAP_DATA, ldapdata); if (ldapdata->ldap) { return Qnil; } switch (rb_scan_args (argc, argv, "02", &host, &port)) { case 0: chost = ALLOCA_N (char, strlen ("localhost") + 1); strcpy (chost, "localhost"); cport = LDAP_PORT; break; case 1: chost = StringValueCStr (host); cport = LDAP_PORT; break; case 2: chost = StringValueCStr (host); cport = NUM2INT (port); break; default: rb_bug ("rb_ldap_conn_new"); }; cldap = ldap_init (chost, cport); if (!cldap) rb_raise (rb_eLDAP_ResultError, "can't initialise an LDAP session"); ldapdata->ldap = cldap; rb_iv_set (self, "@args", rb_ary_new4 (argc, argv)); /* Silence warning that next rb_iv_get produces. */ if (ruby_verbose == Qtrue) { was_verbose = Qtrue; ruby_verbose = Qfalse; } if (rb_iv_get (self, "@sasl_quiet") != Qtrue) rb_iv_set (self, "@sasl_quiet", Qfalse); if (was_verbose == Qtrue) ruby_verbose = Qtrue; return Qnil; }; /* * call-seq: * LDAP::Conn.open(host='localhost', port=LDAP_PORT) => LDAP::Conn * * Return a new LDAP::Conn connection to the server, +host+, on port +port+. */ VALUE rb_ldap_conn_s_open (int argc, VALUE argv[], VALUE klass) { LDAP *cldap; char *chost; int cport; VALUE host, port; VALUE conn; switch (rb_scan_args (argc, argv, "02", &host, &port)) { case 0: chost = ALLOCA_N (char, strlen ("localhost") + 1); strcpy (chost, "localhost"); cport = LDAP_PORT; break; case 1: chost = StringValueCStr (host); cport = LDAP_PORT; break; case 2: chost = StringValueCStr (host); cport = NUM2INT (port); break; default: rb_bug ("rb_ldap_conn_new"); }; cldap = ldap_open (chost, cport); if (!cldap) rb_raise (rb_eLDAP_ResultError, "can't open an LDAP session"); conn = rb_ldap_conn_new (klass, cldap); return conn; }; /* * call-seq: * LDAP::Conn.open_uri(uri) => LDAP::Conn * * Return a new LDAP::Conn connection to the server described with +uri+. */ VALUE rb_ldap_conn_s_open_uri (VALUE klass, VALUE uri) { LDAP *cldap = NULL; int rc; rc = ldap_initialize (&cldap, StringValueCStr (uri)); if (rc || cldap == NULL) rb_raise (rb_eLDAP_ResultError, "can't open an LDAP session"); return rb_ldap_conn_new (klass, cldap); }; /* * call-seq: * conn.start_tls => nil * * Initiate START_TLS for the connection, +conn+. */ VALUE rb_ldap_conn_start_tls_s (int argc, VALUE argv[], VALUE self) { #ifdef HAVE_LDAP_START_TLS_S VALUE arg1, arg2; RB_LDAP_DATA *ldapdata; LDAPControl **serverctrls; LDAPControl **clientctrls; switch (rb_scan_args (argc, argv, "02", &arg1, &arg2)) { case 0: serverctrls = NULL; clientctrls = NULL; break; case 1: case 2: rb_notimplement (); default: rb_bug ("rb_ldap_conn_start_tls_s"); }; GET_LDAP_DATA (self, ldapdata); ldapdata->err = ldap_start_tls_s (ldapdata->ldap, serverctrls, clientctrls); Check_LDAP_Result (ldapdata->err); #else rb_notimplement (); #endif return Qnil; }; VALUE rb_ldap_conn_rebind (VALUE self) { VALUE ary = rb_iv_get (self, "@args"); if (rb_obj_is_kind_of (self, rb_cLDAP_SSLConn) == Qtrue) return rb_ldap_sslconn_initialize (RARRAY_LEN (ary), RARRAY_PTR (ary), self); else return rb_ldap_conn_initialize (RARRAY_LEN (ary), RARRAY_PTR (ary), self); } /* * call-seq: * conn.simple_bind(dn=nil, password=nil) => self * conn.simple_bind(dn=nil, password=nil) { |conn| } => nil * * Bind an LDAP connection, using the DN, +dn+, and the credential, +password+. * If a block is given, +self+ is yielded to the block. */ VALUE rb_ldap_conn_simple_bind_s (int argc, VALUE argv[], VALUE self) { RB_LDAP_DATA *ldapdata; VALUE arg1, arg2; char *dn = NULL; char *passwd = NULL; Data_Get_Struct (self, RB_LDAP_DATA, ldapdata); if (!ldapdata->ldap) { if (rb_iv_get (self, "@args") != Qnil) { rb_ldap_conn_rebind (self); GET_LDAP_DATA (self, ldapdata); } else { rb_raise (rb_eLDAP_InvalidDataError, "The LDAP handler has already unbound."); } } if (ldapdata->bind) { rb_raise (rb_eLDAP_Error, "already bound."); }; switch (rb_scan_args (argc, argv, "02", &arg1, &arg2)) { case 0: break; case 1: if (arg1 == Qnil) { dn = NULL; } else { dn = StringValueCStr (arg1); } break; case 2: if (arg1 == Qnil) { dn = NULL; } else { dn = StringValueCStr (arg1); } if (arg2 == Qnil) { passwd = NULL; } else { passwd = StringValueCStr (arg2); } break; default: rb_bug ("rb_ldap_conn_simple_bind_s"); } ldapdata->err = ldap_simple_bind_s (ldapdata->ldap, dn, passwd); Check_LDAP_Result (ldapdata->err); ldapdata->bind = 1; if (rb_block_given_p ()) { rb_ensure (rb_yield, self, rb_ldap_conn_unbind, self); return Qnil; } else { return self; }; }; /* * call-seq: * conn.bind(dn=nil, password=nil, method=LDAP::LDAP_AUTH_SIMPLE) * => self * conn.bind(dn=nil, password=nil, method=LDAP::LDAP_AUTH_SIMPLE) * { |conn| } => nil * * Bind an LDAP connection, using the DN, +dn+, the credential, +password+, * and the bind method, +method+. If a block is given, +self+ is yielded to * the block. */ VALUE rb_ldap_conn_bind_s (int argc, VALUE argv[], VALUE self) { RB_LDAP_DATA *ldapdata; VALUE arg1, arg2, arg3; char *dn = NULL; char *passwd = NULL; int method = LDAP_AUTH_SIMPLE; Data_Get_Struct (self, RB_LDAP_DATA, ldapdata); if (!ldapdata->ldap) { if (rb_iv_get (self, "@args") != Qnil) { rb_ldap_conn_rebind (self); GET_LDAP_DATA (self, ldapdata); } else { rb_raise (rb_eLDAP_InvalidDataError, "The LDAP handler has already unbound."); } } if (ldapdata->bind) { rb_raise (rb_eLDAP_Error, "already bound."); }; switch (rb_scan_args (argc, argv, "03", &arg1, &arg2, &arg3)) { case 0: break; case 1: dn = StringValueCStr (arg1); break; case 2: dn = StringValueCStr (arg1); passwd = StringValueCStr (arg2); break; case 3: dn = StringValueCStr (arg1); passwd = StringValueCStr (arg2); method = NUM2INT (arg3); break; default: rb_bug ("rb_ldap_conn_bind_s"); } ldapdata->err = ldap_bind_s (ldapdata->ldap, dn, passwd, method); Check_LDAP_Result (ldapdata->err); ldapdata->bind = 1; if (rb_block_given_p ()) { rb_ensure (rb_yield, self, rb_ldap_conn_unbind, self); return Qnil; } else { return self; }; }; /* * call-seq: * conn.unbind => nil * * Unbind the LDAP connection from the server. */ VALUE rb_ldap_conn_unbind (VALUE self) { RB_LDAP_DATA *ldapdata; GET_LDAP_DATA (self, ldapdata); ldapdata->err = ldap_unbind (ldapdata->ldap); ldapdata->bind = 0; ldapdata->ldap = NULL; Check_LDAP_Result (ldapdata->err); return Qnil; }; /* * call-seq: * conn.bound? => true or false * * Return *true* if the LDAP connection is still bound. */ VALUE rb_ldap_conn_bound (VALUE self) { RB_LDAP_DATA *ldapdata; Data_Get_Struct (self, RB_LDAP_DATA, ldapdata); return ldapdata->bind == 0 ? Qfalse : Qtrue; }; /* * call-seq: * conn.set_option(option, data) => self * * Set a session-wide option for this LDAP connection. * * For example: * * conn.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 ) * * would set the protocol of this connection to LDAPv3. */ VALUE rb_ldap_conn_set_option (VALUE self, VALUE opt, VALUE data) { /* ldap_set_option() is defined in IETF draft */ #ifdef HAVE_LDAP_SET_OPTION RB_LDAP_DATA *ldapdata; RB_LDAP_DATA dummy; int idata; void *optdata; int copt; if (NIL_P (self)) { dummy.ldap = NULL; dummy.err = dummy.bind = 0; ldapdata = &dummy; } else GET_LDAP_DATA (self, ldapdata); copt = NUM2INT (opt); switch (copt) { #if defined(USE_OPENLDAP1) || defined(USE_OPENLDAP2) case LDAP_OPT_NETWORK_TIMEOUT: { struct timeval tv; tv = rb_time_interval(data); optdata = &tv; } break; #endif case LDAP_OPT_REFERRALS: optdata = (void *) NUM2INT (data); break; case LDAP_OPT_DEREF: case LDAP_OPT_SIZELIMIT: case LDAP_OPT_TIMELIMIT: case LDAP_OPT_RESTART: case LDAP_OPT_PROTOCOL_VERSION: if (ldapdata->bind != 0) rb_raise (rb_eLDAP_ResultError, "can't set LDAP protocol version after bind"); case LDAP_OPT_ERROR_NUMBER: #ifdef LDAP_OPT_SSL case LDAP_OPT_SSL: #endif #ifdef USE_OPENLDAP2 #ifdef LDAP_OPT_X_TLS case LDAP_OPT_X_TLS: #endif #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT case LDAP_OPT_X_TLS_REQUIRE_CERT: #endif #endif idata = NUM2INT (data); optdata = &idata; break; case LDAP_OPT_HOST_NAME: case LDAP_OPT_ERROR_STRING: #ifdef LDAP_OPT_MATCHED_DN case LDAP_OPT_MATCHED_DN: #endif #ifdef USE_OPENLDAP2 #ifdef LDAP_OPT_X_TLS_CACERTFILE case LDAP_OPT_X_TLS_CACERTFILE: #endif #ifdef LDAP_OPT_X_TLS_CACERTDIR case LDAP_OPT_X_TLS_CACERTDIR: #endif #ifdef LDAP_OPT_X_TLS_CERT case LDAP_OPT_X_TLS_CERT: #endif #ifdef LDAP_OPT_X_TLS_CERTFILE case LDAP_OPT_X_TLS_CERTFILE: #endif #ifdef LDAP_OPT_X_TLS_KEYFILE case LDAP_OPT_X_TLS_KEYFILE: #endif #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN case LDAP_OPT_X_TLS_PROTOCOL_MIN: #endif #ifdef LDAP_OPT_X_TLS_CIPHER_SUITE case LDAP_OPT_X_TLS_CIPHER_SUITE: #endif #ifdef LDAP_OPT_X_TLS_RANDOM_FILE case LDAP_OPT_X_TLS_RANDOM_FILE: #endif #endif optdata = NIL_P (data) ? NULL : StringValueCStr (data); break; #ifdef LDAP_OPT_API_INFO case LDAP_OPT_API_INFO: rb_raise (rb_eLDAP_Error, "option is read-only"); /* optdata = (void*)rb_ldap_get_apiinfo(data); */ break; #endif #ifdef LDAP_OPT_SERVER_CONTROLS case LDAP_OPT_SERVER_CONTROLS: optdata = rb_ldap_get_controls (data); break; #endif default: rb_notimplement (); } ldapdata->err = ldap_set_option (ldapdata->ldap, copt, optdata); Check_LDAP_OPT_Result (ldapdata->err); return self; #else rb_notimplement (); #endif }; static VALUE rb_ldap_conn_s_set_option (VALUE klass, VALUE opt, VALUE data) { return rb_ldap_conn_set_option (Qnil, opt, data); } /* call-seq: * conn.get_option(opt) => String * * Return the value associated with the option, +opt+. */ VALUE rb_ldap_conn_get_option (VALUE self, VALUE opt) { #ifdef HAVE_LDAP_GET_OPTION RB_LDAP_DATA *ldapdata; static RB_LDAP_DATA dummy = { NULL, 0, 0 }; long *data; int copt; VALUE val; if (NIL_P (self)) { if (dummy.ldap == NULL) dummy.ldap = ldap_init ("", 0); ldapdata = &dummy; } else GET_LDAP_DATA (self, ldapdata); copt = NUM2INT (opt); #if defined(LDAP_OPT_API_INFO) && defined(LDAP_API_INFO_VERSION) if (copt == LDAP_OPT_API_INFO) { LDAPAPIInfo *info; info = ALLOCA_N (LDAPAPIInfo, 1); /* This is from the Netscape SDK docs for 4.1* */ info->ldapai_info_version = LDAP_API_INFO_VERSION; ldapdata->err = ldap_get_option (NULL, copt, (void *) info); data = (long *) info; } #if defined(USE_OPENLDAP1) || defined(USE_OPENLDAP2) else if (copt == LDAP_OPT_NETWORK_TIMEOUT) { struct timeval tv; ldapdata->err = ldap_get_option (ldapdata->ldap, copt, &tv); if (!tv.tv_sec) { long x = -1; data = &x; } else data = (void *) tv.tv_sec; } #endif else { data = (void *) ALLOCA_N (char, LDAP_GET_OPT_MAX_BUFFER_SIZE); ldapdata->err = ldap_get_option (ldapdata->ldap, copt, (void *) data); } #else data = (void *) ALLOCA_N (char, LDAP_GET_OPT_MAX_BUFFER_SIZE); ldapdata->err = ldap_get_option (ldapdata->ldap, copt, (void *) data); #endif if (ldapdata->err == LDAP_OPT_SUCCESS) { switch (copt) { case LDAP_OPT_DEREF: case LDAP_OPT_SIZELIMIT: case LDAP_OPT_TIMELIMIT: case LDAP_OPT_REFERRALS: case LDAP_OPT_RESTART: case LDAP_OPT_PROTOCOL_VERSION: case LDAP_OPT_ERROR_NUMBER: #if defined(USE_OPENLDAP1) || defined(USE_OPENLDAP2) case LDAP_OPT_NETWORK_TIMEOUT: #endif #ifdef USE_OPENLDAP2 #ifdef LDAP_OPT_X_TLS case LDAP_OPT_X_TLS: #endif #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT case LDAP_OPT_X_TLS_REQUIRE_CERT: #endif #endif val = INT2NUM ((int) (*data)); break; case LDAP_OPT_HOST_NAME: case LDAP_OPT_ERROR_STRING: #ifdef LDAP_OPT_MATCHED_DN case LDAP_OPT_MATCHED_DN: #endif #ifdef USE_OPENLDAP2 #ifdef LDAP_OPT_X_TLS_CACERTFILE case LDAP_OPT_X_TLS_CACERTFILE: #endif #ifdef LDAP_OPT_X_TLS_CACERTDIR case LDAP_OPT_X_TLS_CACERTDIR: #endif #ifdef LDAP_OPT_X_TLS_CERT case LDAP_OPT_X_TLS_CERT: #endif #ifdef LDAP_OPT_X_TLS_CERTFILE case LDAP_OPT_X_TLS_CERTFILE: #endif #ifdef LDAP_OPT_X_TLS_KEYFILE case LDAP_OPT_X_TLS_KEYFILE: #endif #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN case LDAP_OPT_X_TLS_PROTOCOL_MIN: #endif #ifdef LDAP_OPT_X_TLS_CIPHER_SUITE case LDAP_OPT_X_TLS_CIPHER_SUITE: #endif #ifdef LDAP_OPT_X_TLS_RANDOM_FILE case LDAP_OPT_X_TLS_RANDOM_FILE: #endif #endif val = (data && *data) ? rb_tainted_str_new2 ((char *) (*data)) : Qnil; break; #ifdef LDAP_OPT_API_INFO case LDAP_OPT_API_INFO: val = rb_ldap_apiinfo_new ((LDAPAPIInfo *) data); break; #endif default: rb_notimplement (); }; return val; } else { rb_raise (rb_eLDAP_Error, "%s", ldap_err2string (ldapdata->err)); }; #else rb_notimplement (); #endif }; static VALUE rb_ldap_conn_s_get_option (VALUE klass, VALUE opt) { return rb_ldap_conn_get_option (Qnil, opt); } /* * call-seq: * conn.perror(msg) => nil * * Print the text string associated with the error code of the last LDAP * operation. +msg+ is used to prefix the error. */ VALUE rb_ldap_conn_perror (VALUE self, VALUE msg) { RB_LDAP_DATA *ldapdata; char *cmsg; #if (! defined(HAVE_LDAP_PERROR)) || defined(USE_NETSCAPE_SDK) char *str; #endif GET_LDAP_DATA (self, ldapdata); cmsg = StringValueCStr (msg); #if defined(HAVE_LDAP_PERROR) && (! defined(USE_NETSCAPE_SDK)) ldap_perror (ldapdata->ldap, cmsg); #else str = ldap_err2string (ldapdata->err); fprintf (stderr, "%s: %s\n", cmsg, str); #endif return Qnil; }; /* * call-seq: * conn.result2error(msg) => Fixnum * * Return the error code associated with the LDAP message, +msg+. */ VALUE rb_ldap_conn_result2error (VALUE self, VALUE msg) { RB_LDAP_DATA *ldapdata; RB_LDAPENTRY_DATA *edata; int cdofree = 0; GET_LDAP_DATA (self, ldapdata); Check_Kind (msg, rb_cLDAP_Entry); GET_LDAPENTRY_DATA (msg, edata); ldapdata->err = ldap_result2error (ldapdata->ldap, edata->msg, cdofree); return INT2NUM (ldapdata->err); }; /* * call-seq: * conn.err2string(err) => String * * Return the text string associated with the LDAP error, +err+. */ VALUE rb_ldap_conn_err2string (VALUE self, VALUE err) { RB_LDAP_DATA *ldapdata; int c_err = NUM2INT (err); char *str; GET_LDAP_DATA (self, ldapdata); str = ldap_err2string (c_err); return (str ? rb_tainted_str_new2 (str) : Qnil); }; VALUE rb_ldap_conn_get_errno (VALUE self) { RB_LDAP_DATA *ldapdata; VALUE err; GET_LDAP_DATA (self, ldapdata); #ifdef USE_NETSCAPE_SDK int cerr = ldap_get_lderrno (ldapdata->ldap, NULL, NULL); err = INT2NUM (cerr); #else # ifdef USE_OPENLDAP1 cerr = NUM2INT (ldapdata->ldap->ld_errno); err = INT2NUM (cerr); # else rb_notimplement (); # endif #endif return err; }; static VALUE rb_ldap_conn_invalidate_entry (VALUE msg) { RB_LDAPENTRY_DATA *edata; GET_LDAPENTRY_DATA (msg, edata); edata->ldap = NULL; edata->msg = NULL; return Qnil; }; static int rb_ldap_internal_strcmp (const char *left, const char *right) { VALUE res; if (rb_ldap_sort_obj == Qtrue) { res = rb_funcall (rb_tainted_str_new2 (left), rb_intern ("<=>"), 1, rb_tainted_str_new2 (right)); } else if (rb_ldap_sort_obj != Qnil) { res = rb_funcall (rb_ldap_sort_obj, rb_intern ("call"), 2, rb_tainted_str_new2 (left), rb_tainted_str_new2 (right)); } else { res = 0; }; return INT2NUM (res); }; static int rb_ldap_conn_search_i (int argc, VALUE argv[], VALUE self, RB_LDAP_DATA ** ldapdata, LDAPMessage ** cmsg) { VALUE base, scope, filter, attrs, attrsonly, sec, usec, s_attr, s_proc; LDAP *cldap; char *cbase; int cscope; char *cfilter; char **cattrs; char *sort_attr; int cattrsonly; int i; struct timeval tv; GET_LDAP_DATA (self, (*ldapdata)); cldap = (*ldapdata)->ldap; cattrs = NULL; cattrsonly = 0; tv.tv_sec = 0; tv.tv_usec = 0; sort_attr = NULL; rb_ldap_sort_obj = Qnil; switch (rb_scan_args (argc, argv, "36", &base, &scope, &filter, &attrs, &attrsonly, &sec, &usec, &s_attr, &s_proc)) { case 9: rb_ldap_sort_obj = s_proc; /* Ruby's GC never starts in a C function */ case 8: if (rb_ldap_sort_obj == Qnil) { rb_ldap_sort_obj = Qtrue; } sort_attr = StringValueCStr (s_attr); case 7: tv.tv_usec = NUM2INT (usec); case 6: tv.tv_sec = NUM2INT (sec); case 5: cattrsonly = (attrsonly == Qtrue) ? 1 : 0; case 4: if (TYPE (attrs) == T_NIL) { cattrs = NULL; } else { if (TYPE (attrs) == T_STRING) attrs = rb_ary_to_ary (attrs); else Check_Type (attrs, T_ARRAY); if (RARRAY_LEN (attrs) == 0) { cattrs = NULL; } else { cattrs = ALLOCA_N (char *, (RARRAY_LEN (attrs) + 1)); for (i = 0; i < RARRAY_LEN (attrs); i++) { cattrs[i] = StringValueCStr (RARRAY_PTR (attrs)[i]); }; cattrs[RARRAY_LEN (attrs)] = NULL; } } case 3: cbase = StringValueCStr (base); cscope = NUM2INT (scope); cfilter = StringValueCStr (filter); break; default: rb_bug ("rb_ldap_conn_search_s"); }; (*cmsg) = NULL; if (tv.tv_sec == 0 && tv.tv_usec == 0) { (*ldapdata)->err = ldap_search_s (cldap, cbase, cscope, cfilter, cattrs, cattrsonly, cmsg); } else { (*ldapdata)->err = ldap_search_st (cldap, cbase, cscope, cfilter, cattrs, cattrsonly, &tv, cmsg); } if (!(cmsg && (*cmsg))) { rb_raise (rb_eRuntimeError, "no result returned by search"); } Check_LDAP_Result ((*ldapdata)->err); #ifdef HAVE_LDAP_SORT_ENTRIES if (rb_ldap_sort_obj != Qnil) { ldap_sort_entries ((*ldapdata)->ldap, cmsg, sort_attr, rb_ldap_internal_strcmp); }; #endif rb_ldap_sort_obj = Qnil; return (*ldapdata)->err; } static VALUE rb_ldap_conn_search_b (VALUE rdata) { void **data = (void **) rdata; LDAP *cldap = (LDAP *) data[0]; LDAPMessage *cmsg = (LDAPMessage *) data[1]; LDAPMessage *e; VALUE m; for (e = ldap_first_entry (cldap, cmsg); e != NULL; e = ldap_next_entry (cldap, e)) { m = rb_ldap_entry_new (cldap, e); rb_ensure (rb_yield, m, rb_ldap_conn_invalidate_entry, m); } return Qnil; } static VALUE rb_ldap_conn_search2_b (VALUE rdata) { void **data = (void *) rdata; LDAP *cldap = (LDAP *) data[0]; LDAPMessage *cmsg = (LDAPMessage *) data[1]; VALUE ary = (VALUE) data[2]; LDAPMessage *e; VALUE m; VALUE hash; for (e = ldap_first_entry (cldap, cmsg); e != NULL; e = ldap_next_entry (cldap, e)) { m = rb_ldap_entry_new (cldap, e); hash = rb_ldap_entry_to_hash (m); rb_ary_push (ary, hash); if (rb_block_given_p ()) { rb_ensure (rb_yield, hash, rb_ldap_conn_invalidate_entry, m); } } return Qnil; } static VALUE rb_ldap_msgfree (VALUE data) { LDAPMessage *cmsg = (LDAPMessage *) data; ldap_msgfree (cmsg); return Qnil; } VALUE rb_ldap_parse_result (LDAP * cldap, LDAPMessage * cmsg) { int rc, err, i; char **referrals; LDAPControl **serverctrls; VALUE refs, ctls, ary; refs = rb_ary_new (); ctls = rb_ary_new (); ary = rb_ary_new (); rc = ldap_parse_result (cldap, cmsg, &err, NULL, NULL, &referrals, &serverctrls, 0); Check_LDAP_Result (rc); Check_LDAP_Result (err); if (referrals) { for (i = 0; referrals[i]; i++) { rb_ary_push (refs, rb_str_new2 (referrals[i])); } } if (serverctrls) { for (i = 0; serverctrls[i]; i++) { rb_ary_push (ctls, rb_ldap_control_new2 (serverctrls[i])); } } rb_ary_push (ary, refs); rb_ary_push (ary, ctls); return ary; } /* * call-seq: * conn.search(base_dn, scope, filter, attrs=nil, attrsonly=false, * sec=0, usec=0, s_attr=nil, s_proc=nil) { |entry| } => self * * Perform a search, with the base DN +base_dn+, a scope of +scope+ and a * search filter of +filter+. * * If +attrs+ is present, it should be an array of the attributes that the * search should return. By default, all attributes are returned, which is the * same as specifying an empty array or *nil*. Alternatively, +attrs+ may be a * single string, in which case it will be treated as a single element array. * * If +attrsonly+ is *true*, attributes will be returned, but not their values. * * If +sec+ and/or +usec+ are given, they define the time-out for the search in * seconds and microseconds, respectively. * * If +s_attr+ is given, it specifies the attribute on which to sort the * entries returned by the server. If +s_proc+ is given, it specifies a Proc * object that will be used to sort the entries returned by the server. * * Note that not all results may be returned by this method. If a * size limit has been set for the number of results to be returned and this * limit is exceeded, the results set will be truncated. You can check for * this by calling LDAP::Conn#err immediately after this method and comparing * the result to LDAP::LDAP_SIZELIMIT_EXCEEDED. */ VALUE rb_ldap_conn_search_s (int argc, VALUE argv[], VALUE self) { RB_LDAP_DATA *ldapdata; LDAPMessage *cmsg; LDAP *cldap; VALUE rc_ary = Qnil; rb_ldap_conn_search_i (argc, argv, self, &ldapdata, &cmsg); cldap = ldapdata->ldap; if (ldapdata->err == LDAP_SUCCESS || ldapdata->err == LDAP_SIZELIMIT_EXCEEDED) { void *pass_data[] = { (void *) cldap, (void *) cmsg }; rc_ary = rb_ldap_parse_result (cldap, cmsg); rb_iv_set (self, "@referrals", rb_ary_shift (rc_ary)); rb_iv_set (self, "@controls", rb_ary_shift (rc_ary)); rb_ensure (rb_ldap_conn_search_b, (VALUE) pass_data, rb_ldap_msgfree, (VALUE) cmsg); }; return self; } /* * call-seq: * conn.search2(base_dn, scope, filter, attrs=nil, attrsonly=false, * sec=0, usec=0, s_attr=nil, s_proc=nil) => array * conn.search2(base_dn, scope, filter, attrs=nil, attrsonly=false, * sec=0, usec=0, s_attr=nil, s_proc=nil) { |entry_as_hash| } => self * * Perform a search, with the base DN +base_dn+, a scope of +scope+ and a * search filter of +filter+. * * If +attrs+ is present, it should be an array of the attributes that the * search should return. By default, all attributes are returned, which is the * same as specifying an empty array or *nil*. Alternatively, +attrs+ may be a * single string, in which case it will be treated as a single element array. * * If +attrsonly+ is *true*, attributes will be returned, but not their values. * * If +sec+ and/or +usec+ are given, they define the time-out for the search in * seconds and microseconds, respectively. * * If +s_attr+ is given, it specifies the attribute on which to sort the * entries returned by the server. If +s_proc+ is given, it specifies a Proc * object that will be used to sort the entries returned by the server. * * Note that not all results may be returned by this method. If a * size limit has been set for the number of results to be returned and this * limit is exceeded, the results set will be truncated. You can check for * this by calling LDAP::Conn#err immediately after this method and comparing * the result to LDAP::LDAP_SIZELIMIT_EXCEEDED. */ VALUE rb_ldap_conn_search2_s (int argc, VALUE argv[], VALUE self) { RB_LDAP_DATA *ldapdata; LDAPMessage *cmsg; LDAP *cldap; VALUE ary = Qnil; VALUE rc_ary = Qnil; rb_ldap_conn_search_i (argc, argv, self, &ldapdata, &cmsg); cldap = ldapdata->ldap; ary = rb_ary_new (); if (ldapdata->err == LDAP_SUCCESS || ldapdata->err == LDAP_SIZELIMIT_EXCEEDED) { void *pass_data[] = { (void *) cldap, (void *) cmsg, (void *) ary }; rc_ary = rb_ldap_parse_result (cldap, cmsg); rb_iv_set (self, "@referrals", rb_ary_shift (rc_ary)); rb_iv_set (self, "@controls", rb_ary_shift (rc_ary)); rb_ensure (rb_ldap_conn_search2_b, (VALUE) pass_data, rb_ldap_msgfree, (VALUE) cmsg); } if (rb_block_given_p ()) { return self; } else { return ary; } } #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_SEARCH_EXT_S) static int rb_ldap_conn_search_ext_i (int argc, VALUE argv[], VALUE self, RB_LDAP_DATA ** ldapdata, LDAPMessage ** cmsg) { VALUE base, scope, filter, attrs, attrsonly; VALUE serverctrls, clientctrls, sec, usec, limit, s_attr, s_proc; LDAP *cldap; char *cbase; int cscope; int climit; char *cfilter; char **cattrs; char *sort_attr; int cattrsonly; int i; struct timeval tv; LDAPControl **sctrls, **cctrls; GET_LDAP_DATA (self, (*ldapdata)); cldap = (*ldapdata)->ldap; cattrs = NULL; cattrsonly = 0; cctrls = NULL; sctrls = NULL; tv.tv_sec = 0; tv.tv_usec = 0; sort_attr = NULL; rb_ldap_sort_obj = Qnil; climit = 0; switch (rb_scan_args (argc, argv, "39", &base, &scope, &filter, &attrs, &attrsonly, &serverctrls, &clientctrls, &sec, &usec, &limit, &s_attr, &s_proc)) { case 12: rb_ldap_sort_obj = s_proc; /* Ruby's GC never start in a C function */ case 11: if (rb_ldap_sort_obj == Qnil) { rb_ldap_sort_obj = Qtrue; } sort_attr = StringValueCStr (s_attr); case 10: climit = NUM2INT (limit); case 9: tv.tv_usec = NUM2INT (usec); case 8: tv.tv_sec = NUM2INT (sec); case 7: cctrls = rb_ldap_get_controls (clientctrls); case 6: sctrls = rb_ldap_get_controls (serverctrls); case 5: cattrsonly = (attrsonly == Qtrue) ? 1 : 0; case 4: if (TYPE (attrs) == T_NIL) { cattrs = NULL; } else { if (TYPE (attrs) == T_STRING) attrs = rb_ary_to_ary (attrs); else Check_Type (attrs, T_ARRAY); if (RARRAY_LEN (attrs) == 0) { cattrs = NULL; } else { cattrs = ALLOCA_N (char *, (RARRAY_LEN (attrs) + 1)); for (i = 0; i < RARRAY_LEN (attrs); i++) { cattrs[i] = StringValueCStr (RARRAY_PTR (attrs)[i]); }; cattrs[RARRAY_LEN (attrs)] = NULL; } } case 3: cbase = StringValueCStr (base); cscope = NUM2INT (scope); cfilter = StringValueCStr (filter); break; default: rb_bug ("rb_ldap_conn_search_s"); }; (*cmsg) = NULL; if (tv.tv_sec == 0 && tv.tv_usec == 0) { (*ldapdata)->err = ldap_search_ext_s (cldap, cbase, cscope, cfilter, cattrs, cattrsonly, sctrls, cctrls, NULL, climit, cmsg); } else { (*ldapdata)->err = ldap_search_ext_s (cldap, cbase, cscope, cfilter, cattrs, cattrsonly, sctrls, cctrls, &tv, climit, cmsg); } Check_LDAP_Result ((*ldapdata)->err); #ifdef HAVE_LDAP_SORT_ENTRIES if (rb_ldap_sort_obj != Qnil) { ldap_sort_entries ((*ldapdata)->ldap, cmsg, sort_attr, rb_ldap_internal_strcmp); }; #endif rb_ldap_sort_obj = Qnil; return (*ldapdata)->err; }; /* * call-seq: * conn.search_ext(base_dn, scope, filter, attrs=nil, attrsonly=false, * sctrls, cctrls, sec=0, usec=0, s_attr=nil, s_proc=nil) * { |entry| } => self * * Perform a search, with the base DN +base_dn+, a scope of +scope+ and a * search filter of +filter+. * * If +attrs+ is present, it should be an array of the attributes that the * search should return. By default, all attributes are returned, which is the * same as specifying an empty array or *nil*. Alternatively, +attrs+ may be a * single string, in which case it will be treated as a single element array. * * If +attrsonly+ is *true*, attributes will be returned, but not their values. * * +sctrls+ is an array of server controls, whilst +cctrls+ is an array of * client controls. * * If +sec+ and/or +usec+ are given, they define the time-out for the search in * seconds and microseconds, respectively. * * If +s_attr+ is given, it specifies the attribute on which to sort the * entries returned by the server. If +s_proc+ is given, it specifies a Proc * object that will be used to sort the entries returned by the server. * * Note that not all results may be returned by this method. If a * size limit has been set for the number of results to be returned and this * limit is exceeded, the results set will be truncated. You can check for * this by calling LDAP::Conn#err immediately after this method and comparing * the result to LDAP::LDAP_SIZELIMIT_EXCEEDED. */ VALUE rb_ldap_conn_search_ext_s (int argc, VALUE argv[], VALUE self) { RB_LDAP_DATA *ldapdata; LDAPMessage *cmsg; LDAP *cldap; VALUE rc_ary = Qnil; rb_ldap_conn_search_ext_i (argc, argv, self, &ldapdata, &cmsg); cldap = ldapdata->ldap; if (ldapdata->err == LDAP_SUCCESS || ldapdata->err == LDAP_SIZELIMIT_EXCEEDED) { void *pass_data[] = { (void *) cldap, (void *) cmsg }; rc_ary = rb_ldap_parse_result (cldap, cmsg); rb_iv_set (self, "@referrals", rb_ary_shift (rc_ary)); rb_iv_set (self, "@controls", rb_ary_shift (rc_ary)); rb_ensure (rb_ldap_conn_search_b, (VALUE) pass_data, rb_ldap_msgfree, (VALUE) cmsg); }; return self; }; /* * call-seq: * conn.search_ext2(base_dn, scope, filter, attrs=nil, * attrsonly=false, sctrls, cctrls, sec=0, usec=0, * s_attr=nil, s_proc=nil) => array * conn.search_ext2(base_dn, scope, filter, attrs=nil, * attrsonly=false, sctrls, cctrls, sec=0, usec=0, * s_attr=nil, s_proc=nil) { |entry_as_hash| } => self * * Perform a search, with the base DN +base_dn+, a scope of +scope+ and a * search filter of +filter+. * * If +attrs+ is present, it should be an array of the attributes that the * search should return. By default, all attributes are returned, which is the * same as specifying an empty array or *nil*. Alternatively, +attrs+ may be a * single string, in which case it will be treated as a single element array. * * If +attrsonly+ is *true*, attributes will be returned, but not their values. * * +sctrls+ is an array of server controls, whilst +cctrls+ is an array of * client controls. * * If +sec+ and/or +usec+ are given, they define the time-out for the search in * seconds and microseconds, respectively. * * If +s_attr+ is given, it specifies the attribute on which to sort the * entries returned by the server. If +s_proc+ is given, it specifies a Proc * object that will be used to sort the entries returned by the server. * * Note that not all results may be returned by this method. If a * size limit has been set for the number of results to be returned and this * limit is exceeded, the results set will be truncated. You can check for * this by calling LDAP::Conn#err immediately after this method and comparing * the result to LDAP::LDAP_SIZELIMIT_EXCEEDED. */ VALUE rb_ldap_conn_search_ext2_s (int argc, VALUE argv[], VALUE self) { RB_LDAP_DATA *ldapdata; LDAPMessage *cmsg; LDAP *cldap; VALUE ary; VALUE rc_ary = Qnil; rb_ldap_conn_search_ext_i (argc, argv, self, &ldapdata, &cmsg); cldap = ldapdata->ldap; ary = rb_ary_new (); if (ldapdata->err == LDAP_SUCCESS || ldapdata->err == LDAP_SIZELIMIT_EXCEEDED) { void *pass_data[] = { (void *) cldap, (void *) cmsg, (void *) ary }; rc_ary = rb_ldap_parse_result (cldap, cmsg); rb_iv_set (self, "@referrals", rb_ary_shift (rc_ary)); rb_iv_set (self, "@controls", rb_ary_shift (rc_ary)); rb_ensure (rb_ldap_conn_search2_b, (VALUE) pass_data, rb_ldap_msgfree, (VALUE) cmsg); } if (rb_block_given_p ()) { return self; } else { return ary; } } #endif /* * call-seq: * conn.add(dn, attrs) => self * * Add an entry with the DN, +dn+, and the attributes, +attrs+. +attrs+ * should be either an array of LDAP#Mod objects or a hash of attribute/value * array pairs. */ VALUE rb_ldap_conn_add_s (VALUE self, VALUE dn, VALUE attrs) { RB_LDAP_DATA *ldapdata; char *c_dn; LDAPMod **c_attrs; int i; switch (TYPE (attrs)) { case T_HASH: attrs = rb_ldap_hash2mods (rb_mLDAP, INT2NUM (LDAP_MOD_ADD | LDAP_MOD_BVALUES), attrs); break; case T_ARRAY: break; default: rb_raise (rb_eTypeError, "must be a hash or an array"); }; GET_LDAP_DATA (self, ldapdata); c_dn = StringValueCStr (dn); c_attrs = ALLOCA_N (LDAPMod *, (RARRAY_LEN (attrs) + 1)); for (i = 0; i < RARRAY_LEN (attrs); i++) { VALUE mod = RARRAY_PTR (attrs)[i]; RB_LDAPMOD_DATA *moddata; Check_Kind (mod, rb_cLDAP_Mod); GET_LDAPMOD_DATA (mod, moddata); c_attrs[i] = moddata->mod; }; c_attrs[i] = NULL; ldapdata->err = ldap_add_s (ldapdata->ldap, c_dn, c_attrs); Check_LDAP_Result (ldapdata->err); return self; }; #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_ADD_EXT_S) /* * call-seq: * conn.add_ext(dn, attrs, sctrls, cctrls) => self * * Add an entry with the DN, +dn+, and the attributes, +attrs+. +attrs+ * should be either an array of LDAP#Mod objects or a hash of attribute/value * array pairs. +sctrls+ is an array of server controls, whilst +cctrls+ is * an array of client controls. */ VALUE rb_ldap_conn_add_ext_s (VALUE self, VALUE dn, VALUE attrs, VALUE serverctrls, VALUE clientctrls) { RB_LDAP_DATA *ldapdata; char *c_dn; LDAPMod **c_attrs; int i; LDAPControl **sctrls, **cctrls; switch (TYPE (attrs)) { case T_HASH: attrs = rb_ldap_hash2mods (rb_mLDAP, INT2NUM (LDAP_MOD_ADD | LDAP_MOD_BVALUES), attrs); break; case T_ARRAY: break; default: rb_raise (rb_eTypeError, "must be a hash or an array"); }; GET_LDAP_DATA (self, ldapdata); c_dn = StringValueCStr (dn); c_attrs = ALLOCA_N (LDAPMod *, (RARRAY_LEN (attrs) + 1)); sctrls = rb_ldap_get_controls (serverctrls); cctrls = rb_ldap_get_controls (clientctrls); for (i = 0; i < RARRAY_LEN (attrs); i++) { VALUE mod = RARRAY_PTR (attrs)[i]; RB_LDAPMOD_DATA *moddata; Check_Kind (mod, rb_cLDAP_Mod); GET_LDAPMOD_DATA (mod, moddata); c_attrs[i] = moddata->mod; }; c_attrs[i] = NULL; ldapdata->err = ldap_add_ext_s (ldapdata->ldap, c_dn, c_attrs, sctrls, cctrls); Check_LDAP_Result (ldapdata->err); return self; } #endif /* * call-seq: * conn.modify(dn, mods) => self * * Modify an entry with the DN, +dn+, and the attributes, +mods+. +mods+ * should be either an array of LDAP#Mod objects or a hash of attribute/value * array pairs. */ VALUE rb_ldap_conn_modify_s (VALUE self, VALUE dn, VALUE attrs) { RB_LDAP_DATA *ldapdata; char *c_dn; LDAPMod **c_attrs; int i; switch (TYPE (attrs)) { case T_HASH: attrs = rb_ldap_hash2mods (rb_mLDAP, INT2NUM (LDAP_MOD_REPLACE | LDAP_MOD_BVALUES), attrs); break; case T_ARRAY: break; default: rb_raise (rb_eTypeError, "must be a hash or an array"); }; GET_LDAP_DATA (self, ldapdata); c_dn = StringValueCStr (dn); c_attrs = ALLOC_N (LDAPMod *, RARRAY_LEN (attrs) + 1); for (i = 0; i < RARRAY_LEN (attrs); i++) { VALUE mod = RARRAY_PTR (attrs)[i]; RB_LDAPMOD_DATA *moddata; Check_Kind (mod, rb_cLDAP_Mod); GET_LDAPMOD_DATA (mod, moddata); c_attrs[i] = moddata->mod; }; c_attrs[i] = NULL; ldapdata->err = ldap_modify_s (ldapdata->ldap, c_dn, c_attrs); Check_LDAP_Result (ldapdata->err); free(c_attrs); return self; }; #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_MODIFY_EXT_S) /* * call-seq: * conn.modify_ext(dn, mods, sctrls, cctrls) => self * * Modify an entry with the DN, +dn+, and the attributes, +mods+. +mods+ * should be either an array of LDAP#Mod objects or a hash of attribute/value * array pairs. +sctrls+ is an array of server controls, whilst +cctrls+ is * an array of client controls. */ VALUE rb_ldap_conn_modify_ext_s (VALUE self, VALUE dn, VALUE attrs, VALUE serverctrls, VALUE clientctrls) { RB_LDAP_DATA *ldapdata; char *c_dn; LDAPMod **c_attrs; int i; LDAPControl **sctrls, **cctrls; switch (TYPE (attrs)) { case T_HASH: attrs = rb_ldap_hash2mods (rb_mLDAP, INT2NUM (LDAP_MOD_REPLACE | LDAP_MOD_BVALUES), attrs); break; case T_ARRAY: break; default: rb_raise (rb_eTypeError, "must be a hash or an array"); }; GET_LDAP_DATA (self, ldapdata); c_dn = StringValueCStr (dn); c_attrs = ALLOC_N (LDAPMod *, RARRAY_LEN (attrs) + 1); sctrls = rb_ldap_get_controls (serverctrls); cctrls = rb_ldap_get_controls (clientctrls); for (i = 0; i < RARRAY_LEN (attrs); i++) { VALUE mod = RARRAY_PTR (attrs)[i]; RB_LDAPMOD_DATA *moddata; Check_Kind (mod, rb_cLDAP_Mod); GET_LDAPMOD_DATA (mod, moddata); c_attrs[i] = moddata->mod; }; c_attrs[i] = NULL; ldapdata->err = ldap_modify_ext_s (ldapdata->ldap, c_dn, c_attrs, sctrls, cctrls); Check_LDAP_Result (ldapdata->err); return self; } #endif /* * call-seq: * conn.modrdn(dn, new_rdn, delete_old_rdn) => self * * Modify the RDN of the entry with DN, +dn+, giving it the new RDN, * +new_rdn+. If +delete_old_rdn+ is *true*, the old RDN value will be deleted * from the entry. */ VALUE rb_ldap_conn_modrdn_s (VALUE self, VALUE dn, VALUE newrdn, VALUE delete_p) { RB_LDAP_DATA *ldapdata; char *c_dn; char *c_newrdn; int c_delete_p; GET_LDAP_DATA (self, ldapdata); c_dn = StringValueCStr (dn); c_newrdn = StringValueCStr (newrdn); c_delete_p = (delete_p == Qtrue) ? 1 : 0; ldapdata->err = ldap_modrdn2_s (ldapdata->ldap, c_dn, c_newrdn, c_delete_p); Check_LDAP_Result (ldapdata->err); return self; }; #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_RENAME_S) /* * call-seq: * conn.rename(dn, new_rdn, new_parent_dn, delete_old_rdn, sctrls, cctrls) => self * * Modify the RDN of the entry with DN, +dn+, giving it the new RDN in * parent +new_parent_dn+, +new_rdn+. If you don't want to change * parent, specify *nil* to +new_parent_dn+. If +delete_old_rdn+ is * *true*, the old RDN value will be deleted from the entry. */ VALUE rb_ldap_conn_rename_s (VALUE self, VALUE dn, VALUE newrdn, VALUE newparentdn, VALUE delete_p, VALUE serverctrls, VALUE clientctrls) { RB_LDAP_DATA *ldapdata; char *c_dn; char *c_newrdn; char *c_newparentdn = NULL; int c_delete_p; LDAPControl **sctrls, **cctrls; GET_LDAP_DATA (self, ldapdata); c_dn = StringValueCStr (dn); c_newrdn = StringValueCStr (newrdn); if (!NIL_P(newparentdn)) { c_newparentdn = StringValueCStr (newparentdn); } c_delete_p = (delete_p == Qtrue) ? 1 : 0; sctrls = rb_ldap_get_controls (serverctrls); cctrls = rb_ldap_get_controls (clientctrls); ldapdata->err = ldap_rename_s (ldapdata->ldap, c_dn, c_newrdn, c_newparentdn, c_delete_p, sctrls, cctrls); Check_LDAP_Result (ldapdata->err); return self; } #endif /* * call-seq: * conn.delete(dn) => self * * Delete the entry with the DN, +dn+. */ VALUE rb_ldap_conn_delete_s (VALUE self, VALUE dn) { RB_LDAP_DATA *ldapdata; char *c_dn; GET_LDAP_DATA (self, ldapdata); c_dn = StringValueCStr (dn); ldapdata->err = ldap_delete_s (ldapdata->ldap, c_dn); Check_LDAP_Result (ldapdata->err); return self; }; #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_DELETE_EXT_S) /* * call-seq: * conn.delete_ext(dn, sctrls, cctrls) => self * * Delete the entry with the DN, +dn+. +sctrls+ is an array of server * controls, whilst +cctrls+ is an array of client controls. */ VALUE rb_ldap_conn_delete_ext_s (VALUE self, VALUE dn, VALUE serverctrls, VALUE clientctrls) { RB_LDAP_DATA *ldapdata; char *c_dn; LDAPControl **sctrls, **cctrls; GET_LDAP_DATA (self, ldapdata); c_dn = StringValueCStr (dn); sctrls = rb_ldap_get_controls (serverctrls); cctrls = rb_ldap_get_controls (clientctrls); ldapdata->err = ldap_delete_ext_s (ldapdata->ldap, c_dn, sctrls, cctrls); Check_LDAP_Result (ldapdata->err); return self; } #endif #if defined(HAVE_LDAP_COMPARE_S) /* * call-seq: * conn.compare(dn, attr, val) => true or false * * Compare the DN given as +dn+ to see whether it has the attribute +attr+ * with a value of +val+. */ VALUE rb_ldap_conn_compare_s (VALUE self, VALUE dn, VALUE attr, VALUE val) { RB_LDAP_DATA *ldapdata; char *c_dn, *c_attr, *c_val; GET_LDAP_DATA (self, ldapdata); c_dn = StringValueCStr (dn); c_attr = StringValueCStr (attr); c_val = StringValueCStr (val); ldapdata->err = ldap_compare_s (ldapdata->ldap, c_dn, c_attr, c_val); if ((ldapdata->err) == LDAP_COMPARE_TRUE) return Qtrue; else if ((ldapdata->err) == LDAP_COMPARE_FALSE) return Qfalse; Check_LDAP_Result (ldapdata->err); fprintf (stderr, "rb_ldap_conn_compare_s() unexpectedly set no error.\n"); return self; } #endif #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_COMPARE_EXT_S) /* * call-seq: * conn.compare_ext(dn, attr, val, sctrls, cctrls) => true or false * * Compare the DN given as +dn+ to see whether it has the attribute +attr+ * with a value of +val+. +sctrls+ is an array of server controls, whilst * +cctrls+ is an array of client controls. */ VALUE rb_ldap_conn_compare_ext_s (VALUE self, VALUE dn, VALUE attr, VALUE val, VALUE serverctrls, VALUE clientctrls) { RB_LDAP_DATA *ldapdata; char *c_dn, *c_attr; #ifdef USE_WLDAP32 char *c_val; #endif struct berval bval; LDAPControl **sctrls, **cctrls; GET_LDAP_DATA (self, ldapdata); c_dn = StringValueCStr (dn); c_attr = StringValueCStr (attr); #ifdef USE_WLDAP32 c_val = StringValueCStr (val); #endif bval.bv_val = StringValueCStr (val); bval.bv_len = RSTRING_LEN (val); sctrls = rb_ldap_get_controls (serverctrls); cctrls = rb_ldap_get_controls (clientctrls); ldapdata->err = ldap_compare_ext_s (ldapdata->ldap, c_dn, c_attr, #ifdef USE_WLDAP32 c_val, #endif &bval, sctrls, cctrls); if ((ldapdata->err) == LDAP_COMPARE_TRUE) return Qtrue; else if ((ldapdata->err) == LDAP_COMPARE_FALSE) return Qfalse; Check_LDAP_Result (ldapdata->err); fprintf (stderr, "rb_ldap_conn_compare_ext_s() unexpectedly set no error.\n"); return self; } #endif /* * call-seq: * conn.err => Fixnum * * Return the error associated with the most recent LDAP operation. */ VALUE rb_ldap_conn_err (VALUE self) { RB_LDAP_DATA *ldapdata; GET_LDAP_DATA (self, ldapdata); return INT2NUM (ldapdata->err); }; /* Document-class: LDAP::Conn * * Create and manipulate unencrypted LDAP connections. */ void Init_ldap_conn () { rb_ldap_sort_obj = Qnil; rb_cLDAP_Conn = rb_define_class_under (rb_mLDAP, "Conn", rb_cData); rb_define_attr (rb_cLDAP_Conn, "referrals", 1, 0); rb_define_attr (rb_cLDAP_Conn, "controls", 1, 0); rb_define_attr (rb_cLDAP_Conn, "sasl_quiet", 1, 1); #if RUBY_VERSION_CODE < 170 rb_define_singleton_method (rb_cLDAP_Conn, "new", rb_ldap_class_new, -1); #endif #if RUBY_VERSION_CODE >= 173 rb_define_alloc_func (rb_cLDAP_Conn, rb_ldap_conn_s_allocate); #else rb_define_singleton_method (rb_cLDAP_Conn, "allocate", rb_ldap_conn_s_allocate, 0); #endif rb_define_singleton_method (rb_cLDAP_Conn, "open", rb_ldap_conn_s_open, -1); rb_define_singleton_method (rb_cLDAP_Conn, "open_uri", rb_ldap_conn_s_open_uri, 1); rb_define_singleton_method (rb_cLDAP_Conn, "set_option", rb_ldap_conn_s_set_option, 2); rb_define_singleton_method (rb_cLDAP_Conn, "get_option", rb_ldap_conn_s_get_option, 1); rb_ldap_conn_define_method ("initialize", rb_ldap_conn_initialize, -1); rb_ldap_conn_define_method ("start_tls", rb_ldap_conn_start_tls_s, -1); rb_ldap_conn_define_method ("simple_bind", rb_ldap_conn_simple_bind_s, -1); rb_ldap_conn_define_method ("bind", rb_ldap_conn_bind_s, -1); rb_ldap_conn_define_method ("bound?", rb_ldap_conn_bound, 0); rb_ldap_conn_define_method ("unbind", rb_ldap_conn_unbind, 0); rb_ldap_conn_define_method ("set_option", rb_ldap_conn_set_option, 2); rb_ldap_conn_define_method ("get_option", rb_ldap_conn_get_option, 1); rb_ldap_conn_define_method ("search", rb_ldap_conn_search_s, -1); rb_ldap_conn_define_method ("search2", rb_ldap_conn_search2_s, -1); rb_ldap_conn_define_method ("add", rb_ldap_conn_add_s, 2); rb_ldap_conn_define_method ("modify", rb_ldap_conn_modify_s, 2); rb_ldap_conn_define_method ("modrdn", rb_ldap_conn_modrdn_s, 3); #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_RENAME_S) rb_ldap_conn_define_method ("rename", rb_ldap_conn_rename_s, 6); #endif rb_ldap_conn_define_method ("delete", rb_ldap_conn_delete_s, 1); #if defined(HAVE_LDAP_COMPARE_S) rb_ldap_conn_define_method ("compare", rb_ldap_conn_compare_s, 3); #endif rb_ldap_conn_define_method ("perror", rb_ldap_conn_perror, 1); rb_ldap_conn_define_method ("err2string", rb_ldap_conn_err2string, 1); rb_ldap_conn_define_method ("result2error", rb_ldap_conn_result2error, 1); rb_ldap_conn_define_method ("err", rb_ldap_conn_err, 0); #if defined(HAVE_LDAP_SEARCH_EXT_S) rb_ldap_conn_define_method ("search_ext", rb_ldap_conn_search_ext_s, -1); rb_ldap_conn_define_method ("search_ext2", rb_ldap_conn_search_ext2_s, -1); #endif #if defined(HAVE_LDAP_ADD_EXT_S) rb_ldap_conn_define_method ("add_ext", rb_ldap_conn_add_ext_s, 4); #endif #if defined(HAVE_LDAP_MODIFY_EXT_S) rb_ldap_conn_define_method ("modify_ext", rb_ldap_conn_modify_ext_s, 4); #endif #if defined(HAVE_LDAP_DELETE_EXT_S) rb_ldap_conn_define_method ("delete_ext", rb_ldap_conn_delete_ext_s, 3); #endif #if defined(HAVE_LDAP_COMPARE_EXT_S) rb_ldap_conn_define_method ("compare_ext", rb_ldap_conn_compare_ext_s, 5); #endif }; ruby-ldap-0.9.16/win/0000755000004100000410000000000012260553634014341 5ustar www-datawww-dataruby-ldap-0.9.16/win/winlber.h0000644000004100000410000000066012260553634016156 0ustar www-datawww-data/* -*- C -*- * $Id: winlber.h,v 1.1.1.1 2002/11/06 07:56:34 ttate Exp $ * Copyright (C) 2001 Takaaki Tateishi * References: MSDN Library, OpenLDAP, Cygwin */ #ifndef WINLBER_H #define WINLBER_H #include typedef struct berval { ULONG bv_len; PCHAR bv_val; } LDAP_BERVAL, *PLDAP_BERVAL, BERVAL, *PBERVAL; typedef struct berElement { PCHAR opaque; } BerElement; #endif /* WINLBER_H */ ruby-ldap-0.9.16/win/winldap.h0000644000004100000410000002650612260553634016161 0ustar www-datawww-data/* * $Id: winldap.h,v 1.6 2006/08/08 14:36:15 ianmacd Exp $ * * Copyright (C) 2001 Takaaki Tateishi * Copyright (C) 2006 Ian Macdonald * */ #ifndef WINLDAP_H #define WINLDAP_H #include #define LDAP_VERSION1 1 #define LDAP_VERSION2 2 #define LDAP_VERSION3 3 #define LDAP_VERSION_MIN LDAP_VERSION2 #define LDAP_VERSION LDAP_VERSION2 #define LDAP_VERSION_MAX LDAP_VERSION3 /* #define LDAP_API_VERSION #define LDAP_APIINFO_VERSION */ #define LDAP_VENDOR_NAME "Unknown" #define LDAP_PORT 389 #define LDAP_SLL_PORT 636 #define LDAP_SCOPE_BASE 0x00 #define LDAP_SCOPE_ONELEVEL 0x01 #define LDAP_SCOPE_SUBTREE 0x02 #define LDAP_SUCCESS 0x00 #define LDAP_OPERATIONS_ERROR 0x01 #define LDAP_PROTOCOL_ERROR 0x02 #define LDAP_TIMELIMIT_EXCEEDED 0x03 #define LDAP_SIZELIMIT_EXCEEDED 0x04 #define LDAP_COMPARE_FALSE 0x05 #define LDAP_COMPARE_TRUE 0x06 #define LDAP_AUTH_METHOD_NOT_SUPPORTED 0x07 #define LDAP_STRONG_AUTH_REQUIRED 0x08 #define LDAP_REFERRAL_V2 0x09 #define LDAP_PARTIAL_RESULTS 0x09 #define LDAP_REFERRAL 0x0a #define LDAP_ADMIN_LIMIT_EXCEEDED 0x0b #define LDAP_UNAVAILABLE_CRIT_EXTENSION 0x0c #define LDAP_CONFIDENTIALITY_REQUIRED 0x0d #define LDAP_NO_SUCH_ATTRIBUTE 0x10 #define LDAP_UNDEFINED_TYPE 0x11 #define LDAP_INAPPROPRIATE_MATCHING 0x12 #define LDAP_CONSTRAINT_VIOLATION 0x13 #define LDAP_ATTRIBUTE_OR_VALUE_EXISTS 0x14 #define LDAP_TYPE_OR_VALUE_EXISTS 0x14 #define LDAP_INVALID_SYNTAX 0x15 #define LDAP_NO_SUCH_OBJECT 0x20 #define LDAP_ALIAS_PROBLEM 0x21 #define LDAP_INVALID_DN_SYNTAX 0x22 #define LDAP_IS_LEAF 0x23 #define LDAP_ALIAS_DEREF_PROBLEM 0x24 #define LDAP_INAPPROPRIATE_AUTH 0x30 #define LDAP_INVALID_CREDENTIALS 0x31 #define LDAP_INSUFFICIENT_RIGHTS 0x32 #define LDAP_INSUFFICIENT_ACCESS 0x32 #define LDAP_BUSY 0x33 #define LDAP_UNAVAILABLE 0x34 #define LDAP_UNWILLING_TO_PERFORM 0x35 #define LDAP_LOOP_DETECT 0x36 #define LDAP_NAMING_VIOLATION 0x40 #define LDAP_OBJECT_CLASS_VIOLATION 0x41 #define LDAP_NOT_ALLOWED_ON_NONLEAF 0x42 #define LDAP_NOT_ALLOWED_ON_RDN 0x43 #define LDAP_ALREADY_EXISTS 0x44 #define LDAP_NO_OBJECT_CLASS_MODS 0x45 #define LDAP_RESULTS_TOO_LARGE 0x46 #define LDAP_AFFECTS_MULTIPLE_DSAS 0x47 #define LDAP_OTHER 0x50 #define LDAP_SERVER_DOWN 0x51 #define LDAP_LOCAL_ERROR 0x52 #define LDAP_ENCODING_ERROR 0x53 #define LDAP_DECODING_ERROR 0x54 #define LDAP_TIMEOUT 0x55 #define LDAP_AUTH_UNKNOWN 0x56 #define LDAP_FILTER_ERROR 0x57 #define LDAP_USER_CANCELLED 0x58 #define LDAP_PARAM_ERROR 0x59 #define LDAP_NO_MEMORY 0x5a #define LDAP_CONNECT_ERROR 0x5b #define LDAP_NOT_SUPPORTED 0x5c #define LDAP_CONTROL_NOT_FOUND 0x5d #define LDAP_NO_RESULTS_RETURNED 0x5e #define LDAP_MORE_RESULTS_TO_RETURN 0x5f #define LDAP_CLIENT_LOOP 0x60 #define LDAP_REFERRAL_LIMIT_EXCEEDED 0x61 #define LDAP_MOD_ADD 0x00 #define LDAP_MOD_DELETE 0x01 #define LDAP_MOD_REPLACE 0x02 #define LDAP_MOD_BVALUES 0x80 #define LDAP_AUTH_NONE 0x00 #define LDAP_AUTH_SIMPLE 0x80 #define LDAP_AUTH_SASL 0x83 #define LDAP_AUTH_OTHERKIND 0x86 #define LDAP_AUTH_DPA 0x2000 /* or LDAP_AUTH_OTHERKIND */ #define LDAP_AUTH_MSN 0x0800 /* or LDAP_AUTH_OTHERKIND */ #define LDAP_AUTH_NEGOTIATE 0x0400 /* or LDAP_AUTH_OTHERKIND */ #define LDAP_AUTH_NTLM 0x01000 /* or LDAP_AUTH_OTHERKIND */ #define LDAP_AUTH_SICILY 0x0200 /* or LDAP_AUTH_OTHERKIND */ #define LDAP_AUTH_SSPI LDAP_AUTH_NEGOTIATE #define LDAP_OPT_ON ((void*)1) #define LDAP_OPT_OFF ((void*)0) #define LDAP_OPT_API_INFO 0x00 #define LDAP_OPT_DESC 0x01 #define LDAP_OPT_DEREF 0x02 #define LDAP_OPT_SIZELIMIT 0x03 #define LDAP_OPT_TIMELIMIT 0x04 #define LDAP_OPT_THREAD_FN_PTRS 0x05 #define LDAP_OPT_REBIND_FN 0x06 #define LDAP_OPT_REBIND_ARG 0x07 #define LDAP_OPT_REFERRALS 0x08 #define LDAP_OPT_RESTART 0x09 #define LDAP_OPT_SSL 0x0a #define LDAP_OPT_IO_FN_PTRS 0x0b #define LDAP_OPT_CACHE_FN_PTRS 0x0d #define LDAP_OPT_CACHE_STRATEGY 0x0e #define LDAP_OPT_CACHE_ENABLE 0x0f #define LDAP_OPT_REFERRAL_HOP_LIMIT 0x10 #define LDAP_OPT_PROTOCOL_VERSION 0x11 #define LDAP_OPT_VERSION 0x11 #define LDAP_OPT_API_FEATURE_INFO 0x15 #define LDAP_OPT_HOST_NAME 0x30 #define LDAP_OPT_ERROR_NUMBER 0x31 #define LDAP_OPT_ERROR_STRING 0x32 #define LDAP_OPT_SERVER_ERROR 0x33 #define LDAP_OPT_SERVER_EXT_ERROR 0x34 #define LDAP_OPT_PING_KEEP_ALIVE 0x36 #define LDAP_OPT_PING_WAIT_TIME 0x37 #define LDAP_OPT_PING_LIMIT 0x38 #define LDAP_OPT_DNSDOMAIN_NAME 0x3b #define LDAP_OPT_GETDSNAME_FLAGS 0x3d #define LDAP_OPT_HOST_REACHABLE 0x3e #define LDAP_OPT_PROMPT_CREDENTIALS 0x3f #define LDAP_OPT_TCP_KEEPALIVE 0x40 #define LDAP_OPT_REFERRAL_CALLBACK 0x70 #define LDAP_OPT_CLIENT_CERTIFICATE 0x80 #define LDAP_OPT_SERVER_CERTIFICATE 0x81 #define LDAP_OPT_AUTO_RECONNECT 0x91 #define LDAP_OPT_SSPI_FLAGS 0x92 #define LDAP_OPT_SSL_INFO 0x93 #define LDAP_OPT_REF_DEREF_CONN_PER_MSG 0x94 #define LDAP_OPT_SIGN 0x95 #define LDAP_OPT_ENCRYPT 0x95 #define LDAP_OPT_SASL_METHOD 0x97 #define LDAP_OPT_AREC_EXCLUSIVE 0x98 #define LDAP_OPT_SECURITY_CONTEXT 0x99 #define LDAP_OPT_ROOTDSE_CACHE 0x9a #define LDAP_DEREF_SEARCHING 0x01 #define LDAP_DEREF_FINDING 0x02 #define LDAP_DEREF_ALWAYS 0x03 /* The flags for LDAP_OPT_GETDSNAME_FLAGS: DS_FORCE_REDISCOVERY DS_DIRECTORY_SERVICE_REQUIRED DS_DIRECTORY_SERVICE_PREFERRED DS_GC_SERVER_REQUIRED DS_PDC_REQUIRED DS_WRITABLE_REQUIRED DS_FDC_REQUIRED DS_IP_REQUIRED DS_KDC_REQUIRED DS_TIMESERV_REQUIRED DS_IS_FLAT_NAME DS_IS_DNS_NAME */ struct ldap; typedef struct ldap LDAP, *PLDAP; typedef struct ldapcontrol { PCHAR ldctl_oid; struct berval ldctl_value; BOOLEAN ldctl_iscritical; } LDAPControl, *PLDAPControl; struct ldapmsg; typedef struct ldapmsg LDAPMessage, *PLDAPMessage; typedef struct ldapmod { ULONG mod_op; PCHAR mod_type; union { PCHAR* modv_strvals; struct berval** modv_bvals; }mod_vals; } LDAPMod, *PLDAPMod; typedef struct ldapsortkey { PCHAR sk_attrtype; PCHAR sk_matchruleoid; BOOLEAN sk_reverseorder; } LDAPSortKey, *PLDAPSortKey; /* typedef struct LdapReferralCallback { ULONG SizeOfCallbacks; QUERYFORCONNECTION* QueryForConnection; NOTIFYOFNEWCONNECTION* NotifyRoutine; DEREFERENCECONNECTION* DereferenceRoutine; } LDAP_REFERRAL_CALLBACK, *PLDAP_REFERRAL_CALLBACK; */ struct ldapsearch; typedef struct ldapsearch LDAPSearch, *PLDAPSearch; #if defined(HAVE_SYS_TIME_H) # include #endif typedef struct timeval LDAP_TIMEVAL; typedef struct timeval *PLDAP_TIMEVAL; typedef struct ldapvlvinfo { int ldvlv_version; unsigned long ldvlv_before_count; unsigned long ldvlv_after_count; unsigned long ldvlv_offset; unsigned long ldvlv_count; struct berval* ldvlv_attrvalue; struct berval* ldvlv_context; void* ldvlv_extradata; } LDAPVLVInfo; typedef struct ldap_apifeature_info { int ldapaif_info_version; char* ldapaif_name; int ldapaif_verion; } LDAPAPIFeatureInfo; typedef struct ldapapiinfo { int ldapai_info_version; int ldapai_api_version; int ldapai_protocol_version; char** ldapai_extensions; char* ldapai_vendor_name; int ldapai_vendor_version; } LDAPAPIInfo; ULONG ldap_abandon(LDAP *ld, ULONG msgid); ULONG ldap_abandon_ext(LDAP *ld, ULONG msgid, LDAPControl **sctls, LDAPControl **cctls); LDAP* ldap_init(PCHAR host, ULONG port); LDAP* ldap_sslinit(PCHAR host, ULONG port, int secure); LDAP* ldap_open(PCHAR host, ULONG port); ULONG ldap_bind_s(LDAP *ld, PCHAR who, PCHAR cred, ULONG authmethod); ULONG ldap_unbind_s(LDAP *ld); ULONG ldap_simple_bind_s(LDAP *ld, PCHAR dn, PCHAR passwd); ULONG ldap_add_s(LDAP *ld, PCHAR dn, LDAPMod *attrs[]); ULONG ldap_add_ext_s(LDAP *ld, PCHAR dn, LDAPMod *attrs[], LDAPControl **sctls, LDAPControl **cctls); ULONG ldap_compare_s(LDAP *ld, PCHAR dn, PCHAR attr, PCHAR value); ULONG ldap_compare_ext_s(LDAP *ld, PCHAR dn, PCHAR attr, PCHAR value, struct berval *data, LDAPControl **sctls, LDAPControl **cctls); ULONG ldap_count_entries(LDAP *ld, LDAPMessage *res); ULONG ldap_count_values(PCHAR *vals); ULONG ldap_delete_s(LDAP *ld, PCHAR dn); ULONG ldap_delete_ext_s(LDAP *ld, PCHAR dn, LDAPControl **sctls, LDAPControl **cctls); ULONG ldap_modify_s(LDAP *ld, PCHAR dn, LDAPMod *mods[]); ULONG ldap_modify_ext_s(LDAP *ld, PCHAR dn, LDAPMod *mods[], LDAPControl **sctls, LDAPControl **cctls); ULONG ldap_modrdn_s(LDAP *ld, PCHAR olddn, PCHAR newdn); ULONG ldap_modrdn2_s(LDAP *ld, PCHAR olddn, PCHAR newdn, int delold_flag); ULONG ldap_search_s(LDAP *ld, PCHAR base, ULONG scope, PCHAR filter, PCHAR attrs[], ULONG attrsonly, LDAPMessage **res); ULONG ldap_search_ext_s(LDAP *ld, PCHAR base, ULONG scope, PCHAR filter, PCHAR attrs[], ULONG attrsonly, LDAPControl **sctls, LDAPControl **cctls, struct timeval *timeout, ULONG sizelimit, LDAPMessage **res); ULONG ldap_search_st(LDAP *ld, PCHAR base, ULONG scope, PCHAR filter, PCHAR attrs[], ULONG attrsonly, struct timeval *timeout, LDAPMessage **res); void ldap_perror(LDAP *ld, PCHAR msg); PCHAR ldap_err2string(ULONG err); ULONG ldap_msgfree(LDAPMessage *msg); void ldap_memfree(PCHAR ptr); void ldap_value_free(PCHAR *ptr); void ldap_value_free_len(struct berval **vals); PCHAR ldap_dn2ufn(PCHAR dn); ULONG ldap_ufn2dn(PCHAR ufn, PCHAR *dn); PCHAR ldap_first_attribute(LDAP *ld, LDAPMessage *entry, BerElement **ptr); PCHAR ldap_next_attribute(LDAP *ld, LDAPMessage *entry, BerElement *ptr); LDAPMessage *ldap_first_entry(LDAP *ld, LDAPMessage *res); LDAPMessage *ldap_next_entry(LDAP *ld, LDAPMessage *entry); PCHAR ldap_get_dn(LDAP *ld, LDAPMessage *entry); PCHAR ldap_get_values(LDAP *ld, LDAPMessage *entry, PCHAR attr); struct berval **ldap_get_values_len(LDAP *ld, LDAPMessage *msg, PCHAR attr); ULONG ldap_get_option(LDAP *ld, int option, void *outval); ULONG ldap_set_option(LDAP *ld, int option, void *inval); ULONG ldap_connect(LDAP* ld, PLDAP_TIMEVAL *timeout); #endif /* WINLDAP_H */ ruby-ldap-0.9.16/win/wldap32.def0000644000004100000410000001052512260553634016300 0ustar www-datawww-data; wldap32.def ; ; $Id: wldap32.def,v 1.3 2006/04/19 19:33:00 ianmacd Exp $ ; ; Exports for WLDAP32 DLL ; ; Created by Chris Scharf using instructions from: ; ; http://support.microsoft.com/kb/q131313/ LIBRARY WLDAP32 EXPORTS LdapGetLastError LdapMapErrorToWin32 LdapUTF8ToUnicode LdapUnicodeToUTF8 ber_alloc_t ber_bvdup ber_bvecfree ber_bvfree ber_first_element ber_flatten ber_free ber_init ber_next_element ber_peek_tag ber_printf ber_scanf ber_skip_tag cldap_open cldap_openA cldap_openW ldap_abandon ldap_add ldap_addA ldap_addW ldap_add_ext ldap_add_extA ldap_add_extW ldap_add_ext_s ldap_add_ext_sA ldap_add_ext_sW ldap_add_s ldap_add_sA ldap_add_sW ldap_bind ldap_bindA ldap_bindW ldap_bind_s ldap_bind_sA ldap_bind_sW ldap_check_filterA ldap_check_filterW ldap_cleanup ldap_close_extended_op ldap_compare ldap_compareA ldap_compareW ldap_compare_ext ldap_compare_extA ldap_compare_extW ldap_compare_ext_s ldap_compare_ext_sA ldap_compare_ext_sW ldap_compare_s ldap_compare_sA ldap_compare_sW ldap_conn_from_msg ldap_connect ldap_control_free ldap_control_freeA ldap_control_freeW ldap_controls_free ldap_controls_freeA ldap_controls_freeW ldap_count_entries ldap_count_references ldap_count_values ldap_count_valuesA ldap_count_valuesW ldap_count_values_len ldap_create_page_control ldap_create_page_controlA ldap_create_page_controlW ldap_create_sort_control ldap_create_sort_controlA ldap_create_sort_controlW ldap_create_vlv_controlA ldap_create_vlv_controlW ldap_delete ldap_deleteA ldap_deleteW ldap_delete_ext ldap_delete_extA ldap_delete_extW ldap_delete_ext_s ldap_delete_ext_sA ldap_delete_ext_sW ldap_delete_s ldap_delete_sA ldap_delete_sW ldap_dn2ufn ldap_dn2ufnA ldap_dn2ufnW ldap_encode_sort_controlA ldap_encode_sort_controlW ldap_err2string ldap_err2stringA ldap_err2stringW ldap_escape_filter_element ldap_escape_filter_elementA ldap_escape_filter_elementW ldap_explode_dn ldap_explode_dnA ldap_explode_dnW ldap_extended_operation ldap_extended_operationA ldap_extended_operationW ldap_extended_operation_sA ldap_extended_operation_sW ldap_first_attribute ldap_first_attributeA ldap_first_attributeW ldap_first_entry ldap_first_reference ldap_free_controls ldap_free_controlsA ldap_free_controlsW ldap_get_dn ldap_get_dnA ldap_get_dnW ldap_get_next_page ldap_get_next_page_s ldap_get_option ldap_get_optionA ldap_get_optionW ldap_get_paged_count ldap_get_values ldap_get_valuesA ldap_get_valuesW ldap_get_values_len ldap_get_values_lenA ldap_get_values_lenW ldap_init ldap_initA ldap_initW ldap_memfree ldap_memfreeA ldap_memfreeW ldap_modify ldap_modifyA ldap_modifyW ldap_modify_ext ldap_modify_extA ldap_modify_extW ldap_modify_ext_s ldap_modify_ext_sA ldap_modify_ext_sW ldap_modify_s ldap_modify_sA ldap_modify_sW ldap_modrdn ldap_modrdn2 ldap_modrdn2A ldap_modrdn2W ldap_modrdn2_s ldap_modrdn2_sA ldap_modrdn2_sW ldap_modrdnA ldap_modrdnW ldap_modrdn_s ldap_modrdn_sA ldap_modrdn_sW ldap_msgfree ldap_next_attribute ldap_next_attributeA ldap_next_attributeW ldap_next_entry ldap_next_reference ldap_open ldap_openA ldap_openW ldap_parse_extended_resultA ldap_parse_extended_resultW ldap_parse_page_control ldap_parse_page_controlA ldap_parse_page_controlW ldap_parse_reference ldap_parse_referenceA ldap_parse_referenceW ldap_parse_result ldap_parse_resultA ldap_parse_resultW ldap_parse_sort_control ldap_parse_sort_controlA ldap_parse_sort_controlW ldap_parse_vlv_controlA ldap_parse_vlv_controlW ldap_perror ldap_rename_ext ldap_rename_extA ldap_rename_extW ldap_rename_ext_s ldap_rename_ext_sA ldap_rename_ext_sW ldap_result ldap_result2error ldap_sasl_bindA ldap_sasl_bindW ldap_sasl_bind_sA ldap_sasl_bind_sW ldap_search ldap_searchA ldap_searchW ldap_search_abandon_page ldap_search_ext ldap_search_extA ldap_search_extW ldap_search_ext_s ldap_search_ext_sA ldap_search_ext_sW ldap_search_init_page ldap_search_init_pageA ldap_search_init_pageW ldap_search_s ldap_search_sA ldap_search_sW ldap_search_st ldap_search_stA ldap_search_stW ldap_set_dbg_flags ldap_set_dbg_routine ldap_set_option ldap_set_optionA ldap_set_optionW ldap_simple_bind ldap_simple_bindA ldap_simple_bindW ldap_simple_bind_s ldap_simple_bind_sA ldap_simple_bind_sW ldap_sslinit ldap_sslinitA ldap_sslinitW ldap_start_tls_sA ldap_start_tls_sW ldap_startup ldap_stop_tls_s ldap_ufn2dn ldap_ufn2dnA ldap_ufn2dnW ldap_unbind ldap_unbind_s ldap_value_free ldap_value_freeA ldap_value_freeW ldap_value_free_len ruby-ldap-0.9.16/TODO0000644000004100000410000000040312260553634014231 0ustar www-datawww-data -*- text -*- To-do list ---------- - Support for more LDAPv3 controls and extensions. - DSML support. - (?) adding ldap_url_search_s(), ldap_url_search_st() and ldap_is_ldap_url() - Asynchronous functions. - Correctly implement SASL functions. ruby-ldap-0.9.16/checksums.yaml.gz0000444000004100000410000000065012260553634017033 0ustar www-datawww-data>)RA@ SqrYȡŎI@2r&Ŷa 8ǯCazksy[6B۽$_n{_-k$ Fꪉ5A}( Fpeċt ?%zEF|J*y6p`j0#Id!@* ˥hRcD Cag)(E(-{ HL͞cn߃^39[Ӏr&`ن *ѕnJ,9΀6Ǻ ʴ.ʯ:NWfnJ)DTY6#g{C,4IѦ?ނx`ayיuR?mugE[,TԊضfpLGk* C]#ruby-ldap-0.9.16/ChangeLog0000644000004100000410000010557712260553634015335 0ustar www-datawww-dataFri Sep 6 07:04:07 UTC 2013 Alexey Chebotar * Version 0.9.16 * Fixed undefined method 'each' in LDAP::LDIF.mods_to_ldif (GH-26). Thanks to Francesco Malvezzi. Thu Aug 29 10:18:48 UTC 2013 Alexey Chebotar * Version 0.9.15 * Accept nil for new_parent_dn for rename. Thanks to Kouhei Sutou. Wed Aug 28 13:21:53 UTC 2013 Alexey Chebotar * Version 0.9.14 * Fixed option parsing bug for LDAP::Conn.sasl_bind. Thanks to Brian Leake. * Added possibility to use :nocanon option in rb_ldap_conn_sasl_bind. See ldap_set_option(3) for more information. Thanks to Brian Leake. * Added function conn.rename(dn, new_rdn, new_parent_dn, delete_old_rdn, sctrls, cctrls) => self Modify the RDN of the entry with DN, dn, giving it the new RDN in parent new_parent_dn, new_rdn. If delete_old_rdn is true, the old RDN value will be deleted from the entry. Thanks to Marek Veber. * Added option LDAP_OPT_NETWORK_TIMEOUT for openLDAP. Thanks to David Campbell. * Fixed build error with GCC 4.8.1. Thanks to Kouhei Sutou. * Add missing ldap_raname_s() function availability check. Thanks to Kouhei Sutou. Wed Jun 5 17:44:47 UTC 2013 Alexey Chebotar * Version 0.9.13 * Prevent SyntaxError raised under Ruby 2.0.0 by line 107 regex (invalid multibyte escape). Thanks to Andrew Broman. Tue Dec 27 15:17:03 UTC 2011 Alexey Chebotar * Version 0.9.12 * Enable client certificate authentication for mozilla ldap 6.0 only. Thank to Yuri Arabadji. * New patch for LDAP::Mod data corruption. Thanks to Aprotim Sanyal. * Modify mod_type dangling pointer corruption. Thank you, anon! * Fixed bug in ldap/ldif.rb (GH-6). Thanks to bbense. * Added functions: LDAP::Conn.open_uri(uri); LDAP::explode_dn(dn, notypes); LDAP::explode_rdn(rdn, notypes) Thanks to Marek Veber and Antonio Terceiro. * Fixed many memory leaks. Thanks to Marek Veber and Antonio Terceiro. * Fixed compile with ruby 1.9.2. Thanks to Hiroki Najima. * On windows, the default ldap library became wldap32. Thanks to Hiroki Najima. Mon Mar 15 19:15:49 UTC 2010 Alexey Chebotar * Version 0.9.11 * Allow passing SASL interaction options. Thanks to Anthony M. Martinez. Fri Jan 29 07:50:30 UTC 2010 Alexey Chebotar * Version 0.9.10 * Added controls and referral extraction to #search_ext and #search_ext2. Thanks to Michael Granger. Thu Jun 11 06:51:30 UTC 2009 Alexey Chebotar * Version 0.9.9 * Fixed LDAP::VERSION. Thanks to Kouhei Sutou * Gem Packaging Support. Thanks to S. Potter [mbbx6spp] Tue Apr 21 14:46:38 UTC 2009 Alexey Chebotar * LDAP_OPT_X_TLS_PROTOCOL changed to LDAP_OPT_X_TLS_PROTOCOL_MIN (more information in ITS#5655). Thanks to Milos Jakubicek. Wed Apr 15 11:38:06 UTC 2009 Alexey Chebotar * Fixed regular expression in LDAP::Schema.attr() Thu Mar 25 08:45:02 UTC 2009 Alexey Chebotar * Version 0.9.8. Thu Mar 19 15:22:50 UTC 2009 Alexey Chebotar * Supported Ruby 1.9.x. Wed Aug 9 11:23:04 UTC 2006 Ian Macdonald * Version 0.9.7. Tue Aug 8 14:36:15 UTC 2006 Ian Macdonald * win/winldap.h: LDAP_MOD_DELETE and LDAP_MOD_REPLACE had their values transposed. Thanks to Adam Doligalski . Tue Aug 1 00:12:33 UTC 2006 Ian Macdonald * Version 0.9.6. Tue Aug 1 00:07:53 UTC 2006 Ian Macdonald * conn.c: Minor documentation clarifications. Mon Jul 31 00:38:03 UTC 2006 Ian Macdonald * conn.c: Make clear in documentation that LDAP::Conn#search2 and LDAP::Conn#search_ext2 pass each entry into the block as a hash. Mon Jul 3 22:54:52 UTC 2006 Ian Macdonald * misc.c (Init_ldap_misc): A segmentation fault occurs in ldap.so on FreeBSD when running on AMD64. Change last parameter in rb_struct_define() to be NULL, not 0. Thanks to Mark Kittisopikul and Jan Mikkelsen . Thu Apr 20 16:47:00 UTC 2006 Ian Macdonald * Version 0.9.5. Thu Apr 20 16:39:46 UTC 2006 Ian Macdonald * conn.c (rb_ldap_conn_compare_ext_s): The call to ldap_compare_ext_s() requires an extra argument on Windows platforms. Thu Apr 20 16:34:21 UTC 2006 Ian Macdonald * win/winldap.h: Change prototype for ldap_compare_ext_s() to include extra parameter expected on Windows platforms. Wed Apr 19 22:13:26 UTC 2006 Ian Macdonald * sslconn.c (rb_ldap_sslconn_bind_f): Fix function definition to silence compiler warning. Tue Apr 18 23:40:24 UTC 2006 Ian Macdonald * sslconn.c (rb_ldap_sslconn_bind_f): Function definition was missing an argument. * sslconn.c (rb_ldap_sslconn_bind_s): Erroneously called rb_ldap_sslconn_bind_func() instead of rb_ldap_sslconn_bind_f(). * sslconn.c (rb_ldap_sslconn_simple_bind_s): Erroneously called rb_ldap_sslconn_bind_func() instead of rb_ldap_sslconn_bind_f(). Tue Mar 7 23:49:57 UTC 2006 Ian Macdonald * Version 0.9.4. Tue Mar 7 21:03:01 UTC 2006 Ian Macdonald * conn.c (rb_ldap_conn_search_ext_s): Modify LDAP::Conn#search_ext to treat a return value of LDAP_SIZELIMIT_EXCEEDED from rb_ldap_conn_search_ext_i() as success. * conn.c (rb_ldap_conn_search_ext2_s): Ditto for LDAP::Conn#search_ext2. Mon Mar 6 01:33:10 UTC 2006 Ian Macdonald * sslconn.c (rb_ldap_sslconn_bind_f): New function containing identical code from rb_ldap_sslconn_bind_s() and rb_ldap_sslconn_simple_bind_s(). The new function takes a function pointer as its last parameter, to decide whether to call rb_ldap_conn_bind_s() or rb_ldap_conn_simple_bind_s(), as previously called by rb_ldap_sslconn_bind_s() and rb_ldap_sslconn_simple_bind_s(), respectively. * sslconn.c (rb_ldap_sslconn_bind_s): Code moved to rb_ldap_sslconn_bind_f(). * sslconn.c (rb_ldap_sslconn_simple_bind_s): Code moved to rb_ldap_sslconn_bind_f(). Mon Mar 6 00:28:38 UTC 2006 Ian Macdonald * conn.c (rb_ldap_conn_search_i): Give a clearer exception message when a call to either ldap_search_s(3) or ldap_search_st(3) returns no pointer to a result. Thu Mar 2 12:12:58 UTC 2006 Ian Macdonald * conn.c (rb_ldap_conn_search_s): Modify LDAP::Conn#search to treat a return value of LDAP_SIZELIMIT_EXCEEDED from rb_ldap_conn_search_i() as success. * conn.c (rb_ldap_conn_search2_s): Ditto for LDAP::Conn#search2. * rbldap.h: Check_LDAP_Result macro modifed to treat LDAP_SIZELIMIT_EXCEEDED as success. Thu Mar 2 11:54:22 UTC 2006 Ian Macdonald * conn.c: RDoc documentation was missing for LDAP::Conn#err. Sat Feb 18 09:37:14 UTC 2006 Ian Macdonald * Version 0.9.3 Thu Feb 16 01:15:59 UTC 2006 Ian Macdonald * extconf.rb: Build with -DLDAP_DEPRECATED to enable functions no longer automatically defined by ldap.h in OpenLDAP 2.3. Mon Feb 13 17:20:32 UTC 2006 Ian Macdonald * conn.c (rb_ldap_conn_bind_s): Use RB_LDAP_DATA instead of struct rb_ldap_data. * conn.c (rb_ldap_conn_simple_bind_s): Ditto. * conn.c (rb_ldap_conn_bound): Ditto. * saslconn.c (rb_ldap_conn_sasl_bind): Ditto. Mon Feb 13 17:10:08 UTC 2006 Ian Macdonald * sslconn.c (rb_ldap_sslconn_bind_s): In LDAP::SSLConn#bind, ldapdata was used uninitialised. * sslconn.c (rb_ldap_sslconn_simple_bind_s): Ditto for LDAP::SSLConn#simple_bind. Sun Feb 12 20:33:28 UTC 2006 Ian Macdonald * conn.c (rb_ldap_conn_s_allocate): Silence a warning about @sasl_quiet when run in debug mode. Sun Feb 12 17:28:14 UTC 2006 Ian Macdonald * extconf.rb: Common directory scheme of mkmf.rb is now used. As a side-effect, --with-ldap-incdir has been replaced by --with-ldap-include and --with-ldap-libdir has been replaced by --with-ldap-lib. Thanks to Usa Nakamura . * extconf.rb: Display text was improved and grammatical errors were corrected. Sun Feb 12 17:08:17 UTC 2006 Ian Macdonald * conn.c: Make inclusion of sys/time.h and unistd.h conditional on macro defines. Thanks to Usa Nakamura . * saslconn.c: Ditto. * sslconn.c: Ditto. Sun Feb 12 16:59:06 UTC 2006 Ian Macdonald * win/winldap.h: Fix up various structs for Windows. Thanks to Usa Nakamura for the patch. Thu Feb 8 23:15:17 UTC 2006 Ian Macdonald * lib/ldap/schema.rb: Allow LDAP::Schema#attr to find attribute names that contain hyphens and/or underscores. * lib/ldap/schema.rb: Fix LDAP::Schema#names to not allow all manner of extra characters in names. That was introduced by the last change. Thu Feb 8 22:59:07 UTC 2006 Ian Macdonald * lib/ldap/schema.rb: Relax parsing in LDAP::Schema#names to allow names with hyphens and/or underscores. This is apparently an issue with the Sun LDAP server. Thanks to Tilo Sloboda for pointing out the issue. Tue Jul 5 19:14:38 UTC 2005 Ian Macdonald * Version 0.9.2 * conn.c (rb_ldap_conn_perror): str was not declared, but is needed depending on certain #define macros. Tue Mar 23 10:04:19 UTC 2005 Ian Macdonald * conn.c (rb_ldap_conn_search_i): Allow attrs to be a string, in which case the parameter is treated as a single-element array. This affects Conn#search and Conn#search2. * conn.c (rb_ldap_conn_search_ext_i): Ditto for Conn#search_ext and Conn#search_ext2. Tue Mar 15 10:47:38 UTC 2005 Ian Macdonald * Version 0.9.1 Tue Mar 15 10:18:46 UTC 2005 Ian Macdonald * ldap.c: Removed unused variables to silence gcc warnings. * misc.c: Ditto. * entry.c: Ditto. * conn.c: Ditto. * saslconn.c: Ditto. Mon Mar 14 23:52:58 UTC 2005 Ian Macdonald * conn.c (rb_ldap_conn_rebind): New function, which is called when an unbound connection needs to be rebound. It will then call rb_ldap_conn_initialize() for a Conn object or rb_ldap_sslconn_initialize() for an SSLConn object, passing in the original arguments. * conn.c (rb_ldap_conn_bind_s): In LDAP::Conn#bind, allow rb_ldap_conn_rebind() to rebind a connection that has been unbound. * conn.c (rb_ldap_conn_simple_bind_s): Ditto for LDAP::Conn#simple_bind. * saslconn.c (rb_ldap_conn_sasl_bind): Ditto for LDAP::Conn#sasl_bind. * sslconn.c (rb_ldap_sslconn_bind_s): Ditto for LDAP::SSLConn#bind. * sslconn.c (rb_ldap_sslconn_simple_bind_s): Ditto for LDAP::SSLConn#simple_bind. * conn.c (rb_ldap_conn_initialize): Track original parameters to Conn.new in @args, not @host and @port. * sslconn.c (rb_ldap_sslconn_initialize): Ditto for SSLConn.new. Sun Mar 13 11:08:00 UTC 2005 Ian Macdonald * sslconn.c (rb_openldap_sslconn_initialize): Remove tracking of host and port in @host and @port. * sslconn.c (rb_nssldap_sslconn_initialize): Ditto. * sslconn.c (rb_wldap32_sslconn_initialize): Ditto. * sslconn.c (rb_ldap_sslconn_bind_s): Revert usage of @host and @port to rebind an unbound connection in LDAP::SSLConn#bind. * sslconn.c (rb_ldap_sslconn_simple_bind_s): Ditto for LDAP::SSLConn#simple_bind. Sun Mar 13 10:54:34 UTC 2005 Ian Macdonald * conn.c (rb_ldap_conn_bind_s): In LDAP::Conn#bind, disallow rebinding of connections if they're SSL connections (as SSLConn calls this method in the parent class, Conn), since we don't store the required information about them and we can't allow them to rebind as non-SSL connections. * conn.c (rb_ldap_conn_simple_bind_s): Ditto for LDAP::Conn#simple_bind. * saslconn.c (rb_ldap_conn_sasl_bind): Ditto for LDAP::Conn#sasl_bind. Sun Mar 13 09:40:28 UTC 2005 Ian Macdonald * sslconn.c (rb_ldap_sslconn_s_open): SSLConn#open would call the method in the superclass, Conn#open. If this was passed two parameters, the method appeared to succeed, but did not use SSL. Calling this method now returns NotImplementedError via the new function, rb_ldap_sslconn_s_open(). Sun Mar 13 08:35:15 UTC 2005 Ian Macdonald * sslconn.c (rb_openldap_sslconn_initialize): In LDAP::SSLConn.new, set @host and @port to the host and port of the server to which we are connecting. * sslconn.c (rb_nssldap_sslconn_initialize): Ditto. * sslconn.c (rb_wldap32_sslconn_initialize): Ditto. * sslconn.c (rb_ldap_sslconn_bind_s): The version of LDAP::SSLConn#bind used by WLDAP32 now uses @host and @port to reestablish a connection at bind time if the SSLConn object was previously bound. * sslconn.c (rb_ldap_sslconn_simple_bind_s): Ditto for LDAP::SSLConn#simple_bind. Sat Mar 12 11:32:20 UTC 2005 Ian Macdonald * saslconn.c (rb_ldap_conn_sasl_bind): In LDAP::Conn#sasl_bind, detect attempts to bind more than once. * saslconn.c (rb_ldap_conn_sasl_bind): In LDAP::Conn#sasl_bind, if we have an invalid LDAP data structure in self, we check to see whether both @host and @port are set. If they are, we transparently call rb_ldap_conn_initialize() to revalidate self's LDAP data structure. This enables us to rebind after an unbind operation has destroyed the original LDAP data structure of the LDAP::Conn object. Sat Mar 12 11:27:48 UTC 2005 Ian Macdonald * conn.c (rb_ldap_conn_initialize): In LDAP::Conn.new, only set @sasl_quiet to false if it is not already true, as we may be getting called from LDAP::Conn#sasl_bind if we are rebinding an unbound connection. If so and @sasl_quiet had previously been set to true, we want to keep it that way. Sat Mar 12 10:54:41 UTC 2005 Ian Macdonald * saslconn.c (rb_ldap_conn_sasl_bind): In LDAP::Conn#sasl_bind, automatically set the LDAP protocol to v3 if it is not already so. Sat Mar 12 09:33:24 UTC 2005 Ian Macdonald * conn.c (rb_ldap_conn_bound): LDAP::Conn#bound? was throwing an exception when invoked on a Conn object on which an explicit #unbind had been performed. Sat Mar 12 08:48:56 UTC 2005 Ian Macdonald * conn.c (rb_ldap_conn_simple_bind_s): In LDAP::Conn#simple_bind, if we have an invalid LDAP data structure in self, we check to see whether both @host and @port are set. If they are, we transparently call rb_ldap_conn_initialize() to revalidate self's LDAP data structure. This enables us to rebind after an unbind operation has destroyed the original LDAP data structure of the LDAP::Conn object. Sat Mar 12 08:40:21 UTC 2005 Ian Macdonald * conn.c (rb_ldap_conn_initialize): In LDAP::Conn.new, set @host and @port to the host and port of the server to which we are connecting. * conn.c (rb_ldap_conn_bind_s): In LDAP::Conn#bind, if we have an invalid LDAP data structure in self, we check to see whether both @host and @port are set. If they are, we transparently call rb_ldap_conn_initialize() to revalidate self's LDAP data structure. This enables us to rebind after an unbind operation has destroyed the original LDAP data structure of the LDAP::Conn object. Fri Mar 11 23:58:27 UTC 2005 Ian Macdonald * conn.c (rb_ldap_conn_compare_s): Conn#compare should return true or false, not self. In fact, self was never returned, anyway, because an LDAP::ResultError was thrown. This is because ldap_compare_s() and ldap_compare_ext_s() return an error, not 0 or 1. * conn.c (rb_ldap_conn_compare_ext_s): Ditto for Conn#compare_ext, because ldap_compare_ext_s() works the same way. Tue Mar 8 10:15:37 UTC 2005 Ian Macdonald * entry.c: Make LDAP::Entry#[] an alias of LDAP::Entry#get_values. Tue Mar 8 09:44:50 UTC 2005 Ian Macdonald * conn.c (rb_ldap_conn_search_i): Allow attrs to be nil, which is treated as an empty array. This affects Conn#search and Conn#search2. * conn.c (rb_ldap_conn_search_ext_i): Ditto for Conn#search_ext and Conn#search_ext2. Tue Mar 8 00:46:46 UTC 2005 Ian Macdonald * conn.c (rb_ldap_conn_search_i): attrs should be type-checked to ensure it is an array. This affects Conn#search and Conn#search2. * conn.c (rb_ldap_conn_search_ext_i): Ditto for Conn#search_ext and Conn#search_ext2. * conn.c (rb_ldap_conn_search_ext_i): Check to see whether attrs is an empty array before allocating space. Thu Mar 3 00:26:44 UTC 2005 Ian Macdonald * Version 0.9.0 Tue Mar 1 08:14:25 UTC 2005 Ian Macdonald * lib/ldap/ldif.rb: Ensure that LDIF.parse_entry always creates on an array of lines, not a string, as this is probably faster. Tue Mar 1 02:16:28 UTC 2005 Ian Macdonald * lib/ldap/schema.rb: Extend the list of attributes that LDAP::Conn#root_dse returns by default. We now include monitorContext and supportedFeatures, as returned by OpenLDAP 2.2. Tue Mar 1 01:20:40 UTC 2005 Ian Macdonald * lib/ldap/schema.rb: RDoc documentation added for LDAP::Schema, plus LDAP::Conn#schema and LDAP::Conn#root_dse. Mon Feb 28 10:41:35 UTC 2005 Ian Macdonald * ldap.c: RDoc documentation added for LDAP module functions. Mon Feb 28 09:51:22 UTC 2005 Ian Macdonald * misc.c: RDoc documentation added for LDAP::Control. Mon Feb 28 09:07:42 UTC 2005 Ian Macdonald * mod.c: RDoc documentation added for LDAP::Mod. Mon Feb 28 07:50:52 UTC 2005 Ian Macdonald * entry.c: RDoc documentation added for LDAP::Entry. Mon Feb 28 04:11:43 UTC 2005 Ian Macdonald * saslconn.c (rb_ldap_conn_sasl_bind): Return nil, not self, if a block is passed to LDAP::Conn#sasl_bind. * saslconn.c: RDoc documentation added for LDAP::Conn#sasl_bind. Mon Feb 28 03:34:01 UTC 2005 Ian Macdonald * sslconn.c: RDoc documentation added for LDAP::SSLConn. Fri Feb 26 01:47:14 UTC 2005 Ian Macdonald * lib/ldap/ldif.rb: Add LDIF.mods_to_ldif, which will take a DN and either an LDAP::Mod or an array of LDAP::Mod objects. * lib/ldap/ldif.rb: Rewrite Mod#to_ldif to produce more useful output for a single mod. Fri Feb 25 10:49:42 UTC 2005 Ian Macdonald * conn.c (rb_ldap_conn_modify_s): If passing in a hash, LDAP_MOD_BVALUES should be set, just in case there are mods containing binary values. This affects LDAP::Conn#modify. * conn.c (rb_ldap_conn_modify_ext_s): Ditto for LDAP::Conn#modify_ext. Fri Feb 25 06:51:35 UTC 2005 Ian Macdonald * lib/ldap/ldif.rb: Privatise some classes and make LDIFError inherit from LDAP::Error instead of StandardError. Thu Feb 24 22:09:29 UTC 2005 Ian Macdonald * lib/ldap/ldif.rb: Mask out LDAP_MOD_BVALUES when determining change type in LDAP::Mod#to_ldif. Fri Feb 25 10:34:34 UTC 2005 Ian Macdonald * conn.c: RDoc documentation added for LDAP::Conn. Thu Feb 24 03:24:10 UTC 2005 Ian Macdonald * lib/ldap/ldif.rb: LDIF.to_ldif now private. Thu Feb 24 00:45:45 UTC 2005 Ian Macdonald * lib/ldap/ldif.rb: LDAP::Record#send now returns self. Wed Feb 23 23:54:50 UTC 2005 Ian Macdonald * lib/ldap/ldif.rb: Completely rewritten and now functional. Tue Feb 22 02:36:16 UTC 2005 Ian Macdonald * conn.c (rb_ldap_conn_add_s): If passing in a hash, LDAP_MOD_BVALUES should be set, just in case there are attributes containing binary values. This affects LDAP::Conn#add. * conn.c (rb_ldap_conn_add_ext_s): Ditto for LDAP::Conn#add_ext. Sat Feb 19 17:13:49 UTC 2005 Ian Macdonald * conn.c (Init_ldap_conn): No longer automatically load ldap/control, as Ruby versions before 1.8.2 are missing OpenSSL::ASN1::decode. Thu Feb 15 21:40:58 UTC 2005 Ian Macdonald * mod.c (rb_ldap_mod_inspect): LDAP::Mod#inspect did not do the right thing when LDAP_MOD_BVALUES was set. Thu Feb 8 01:22:28 UTC 2005 Ian Macdonald * Updates to various documentation files. * Version 0.8.4. Thu Feb 3 10:24:36 UTC 2005 Ian Macdonald * mod.c (rb_ldap_mod_inspect): Simplify LDAP::Mod#inspect by converting Mod to a hash and then calling Hash#inspect on that. Thu Feb 3 10:09:00 UTC 2005 Ian Macdonald * entry.c (rb_ldap_entry_inspect): LDAP::Entry#inspect now displays something useful, thanks to this new function. Thu Feb 3 01:49:03 UTC 2005 Ian Macdonald * mod.c (rb_ldap_mod_inspect): LDAP::Mod#inspect did not properly display multi-value attributes. Thu Feb 3 01:04:59 UTC 2005 Ian Macdonald * mod.c (rb_ldap_mod_inspect): New method to implement custom LDAP::Mod#inspect. Thu Feb 2 21:44:10 UTC 2005 Ian Macdonald * lib/ldap/control.rb: - Added LDAP::Control::encode and LDAP::Control#decode for dealing with controls. Tue Feb 1 01:29:38 UTC 2005 Ian Macdonald * conn.c: Fixed grammar in a couple of exception messages. * rbldap.h: Ditto. Mon Jan 31 23:37:41 UTC 2005 Ian Macdonald * conn.c (rb_ldap_conn_bound): Implement LDAP::Conn#bound? to check whether connection is still bound. * conn.c (rb_ldap_conn_set_option): Raise exception if an attempt is made to set protocol version after bind. Fri Dec 17 12:29:52 UTC 2004 Takaaki Tateishi * saslconn.c (rb_ldap_conn_sasl_bind): Merge Ian Macdonald's patch to add sasl_quiet attribute to LDAP::Conn objects. It's false by default, but will silence messages when set to true. This is useful for silencing OpenLDAP SASL messages. * conn.c (rb_ldap_conn_initialize): Initialise @sasl_quiet to false. * sslconn.c (rb_openldap_sslconn_initialize): Ditto. Sun Nov 14 14:31:37 UTC 2004 Takaaki Tateishi * Merge Ian Macdonald's patch to add session-level LDAP controls. LDAP::Conn objects now have two new attributes, @referrals and @controls, which will be used when the server needs to pass controls at the session level. Both LDAP::Conn#search and LDAP::Conn#search2 are capable of reading and setting these controls. Sat Oct 9 09:36:20 UTC 2004 Takaaki Tateishi * version 0.8.3 Mon Feb 16 10:37:11 UTC 2004 Takaaki Tateishi * conn.c: The singleton method Conn.set/get_option() is added. (Thanks Y.Gotou) Tue Dec 23 09:08:50 UTC 2003 Takaaki Tateishi * saslconn.c: Merged Ian's patch to allow SASL GSSAPI. Sat Dec 6 17:35:12 UTC 2003 Takaaki Tateishi * version 0.8.2 Sat Dec 6 17:35:12 UTC 2003 Takaaki Tateishi * conn.c: An array object passed to rb_ensure() shouldn't contain illegal objects such as C pointers. Sat Nov 15 14:19:38 UTC 2003 Takaaki Tateishi * Use StringValueCStr/StringValuePtr instead of STR2CSTR/STR2CPTR. Sat Oct 18 09:02:27 UTC 2003 Takaaki Tateishi * version 0.8.1 Sat Oct 18 09:02:27 UTC 2003 Takaaki Tateishi * conn.c: Fixed the memory leak problem of Conn#search which was reported by Akira Yamada. Mon Oct 6 14:11:01 UTC 2003 Takaaki Tateishi * test/add.rb: Adding an attribute 'dn' and fix the object class for entry1. * Removing the directory 'doc'. * saslconn.c: Get rid of unreachable lines. (Thanks Yuuzou Gotou) Tue Feb 18 18:20:54 UTC 2003 Takaaki Tateishi * saslconn.c: Fixed a Conn#sasl_bind which should throw an exception 'NotImplementedError' since it was not implemented correctly yet. (Thanks Hadmut Danisch) Tue Jan 14 09:14:42 UTC 2003 Takaaki Tateishi * conn.c: Fixed a compile problem for ruby-1.8.x. (Thanks Radek Hnilica) Sat Dec 21 22:00:02 UTC 2002 Takaaki Tateishi * Use rb_define_alloc_func() for ruby-1.7.x. Mon Nov 25 17:38:11 UTC 2002 Takaaki Tateishi * ldap.c: Added LDAP_SASL_SIMPLE. Mon Nov 18 05:42:46 UTC 2002 Takaaki Tateishi * ldap.c: Added LDAP::LDAP_DEREF_NEVER, and so on. * conn.c: Fixed Conn#set_option for LDAP_OPT_REFERRALS. * conn.c: Fixed the problem that Conn#search(dn,scope,filter,attrs) dies when attrs is []. Fri Nov 8 19:30:05 UTC 2002 Takaaki Tateishi * Add Conn#sasl_bind instead of SASLConn, and deleted SASLConn. Tue Nov 5 07:26:24 UTC 2002 Takaaki Tateishi * This project moved to SourceForge, and the license is changed to BSD. Tue Oct 22 16:24:13 UTC 2002 Takaaki Tateishi * misc.c (Init_ldap_misc): Added "#ifdef HAVE_LDAPCONTROL". (Thanks Pirmin Kalberer) Mon Aug 5 03:08:20 UTC 2002 Takaaki Tateishi * version 0.8.0 Sun Aug 4 16:54:53 UTC 2002 Takaaki Tateishi * Conform to the allocation framework. Mon Jul 29 05:13:11 UTC 2002 Takaaki Tateishi * version 0.7.2 Fri Jul 19 06:40:10 UTC 2002 Takaaki Tateishi * win/winldap.h: fix values of LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE. Thu Jul 18 16:22:14 UTC 2002 Takaaki Tateishi * version 0.7.1 Thu Jul 18 16:22:14 UTC 2002 Takaaki Tateishi * conn.c: raise -> rb_raise Wed Jun 5 13:45:25 UTC 2002 Takaaki Tateishi * Use ALLOC_N instead of malloc(). * rb_sLDAP_Control -> rb_cLDAP_Control. Sun Jun 2 15:13:17 UTC 2002 Takaaki Tateishi * version 0.7.0 Sun Jun 2 15:13:17 UTC 2002 Takaaki Tateishi * Improve testing scripts. Sat Jun 1 17:16:16 UTC 2002 Takaaki Tateishi * rbldap.h: define RB_LDAP_SET_STR. * misc.c (rb_ldap_get_apiinfo): should allocate new space for a string. * misc.c (rb_ldap_get_controls): ditto. * mod.c (rb_ldap_mod_s_new): ditto. * conn.c: Add Conn#xxxx_ext() methods. Tue Apr 2 09:01:54 UTC 2002 Takaaki Tateishi * version 0.6.1 Tue Apr 2 03:53:13 UTC 2002 Takaaki Tateishi * conn.c: prohibit multiple bind calls. Fri Mar 29 15:06:56 UTC 2002 Takaaki Tateishi * conn.c: Any operations should not be permitted after the unbind operation. Tue Mar 12 07:44:23 UTC 2002 Takaaki Tateishi * version 0.6.0. Tue Mar 12 06:08:29 UTC 2002 Takaaki Tateishi * conn.c: a few methods return a connection object. Fri Jan 11 19:41:59 JST 2002 Takaaki Tateishi * lib/ldap/schema.rb: new file Wed Jan 2 10:51:05 JST 2002 Takaaki Tateishi * sslconn.c (rb_openldap_sslconn_s_new): Both of LDAPS connection and StartTLS extension are available. * ldap.c: Add LDAP_OPT_SSL for wldap32.dll. Wed Jan 2 04:10:20 JST 2002 Takaaki Tateishi * sslconn.c (rb_wldap32_sslconn_s_new): new function for SSL connection on windows. Tue Jan 1 10:48:04 JST 2002 Takaaki Tateishi * version 0.5.0 Tue Jan 1 10:48:04 JST 2002 Takaaki Tateishi * support wldap32.dll * conn.c (rb_ldap_conn_compare): new method Sun Dec 9 15:36:41 JST 2001 Takaaki Tateishi * version 0.4.0 Sat Dec 8 23:05:08 JST 2001 Takaaki Tateishi * sslconn.c (rb_ldap_sslconn_s_new): call rb_ldap_conn_new(). * saslconn.c (rb_ldap_saslconn_s_new): call rb_ldap_conn_new(). * conn.c (rb_ldap_conn_new): initialize ldapdata->bind by 0. * rbldap.h (Init_ldap_message): unused. Thu Jul 5 22:55:56 JST 2001 Takaaki Tateishi * ldap.c (rb_eLDAP_Error): the super class of the LDAPError became the StandardError. Sun Jul 1 12:06:46 JST 2001 Takaaki Tateishi * ldap.c (Init_ldap): add constants LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION and LDAP_API_VERSION Sat Jun 30 19:45:13 JST 2001 Takaaki Tateishi * saslconn.c (rb_cSASLConn): new class * rbldap.h (Init_xxx): bug fixes * conn.c (rb_ldap_conn_new): use 'klass' as the type of new object Wed Jun 13 22:03:44 JST 2001 Takaaki Tateishi * sslconn.c (rb_openldap_sslconn_s_new): new function * sslconn.c (rb_nssldap_sslconn_s_new): new function * sslconn.c (rb_ldap_sslconn_s_new): using the above two functions Mon Jun 13 23:01:13 JST 2001 Takaaki Tateishi * version 0.3.7 Mon Jun 11 23:01:13 JST 2001 Takaaki Tateishi * rbldap.h: bug fix for OpenLDAP1 (Thanks Akira Yamada) * misc.h: bug fix for OpenLDAP1,2 Mon Jun 11 20:20:19 JST 2001 Takaaki Tateishi * extconf.rb: bug fix for OpenLDAP1 (thanks Akira Yamada) Mon Jun 11 10:55:08 JST 2001 Takaaki Tateishi * version 0.3.6 Tue Jun 5 01:12:00 JST 2001 Amos Gouaux * conn.c (rb_ldap_conn_get_option): bug fix for LDAP_OPT_API_INFO. * conn.c (rb_ldap_conn_set_option): bug fix for LDAP_OPT_API_INFO. (checked with the Netscape SDK 4.14 and the OpenLDAP2.0.11) Wed May 23 11:43:09 JST 2001 Pedro Cuenca * extconf.rb: $ldap_incdir,$ldap_libdir ware not used. Fri May 18 18:54:19 JST 2001 Takaaki Tateishi * ldap.c (rb_ldap_hash2mods): new function * conn.c (rb_ldap_conn_add_s, rb_ldap_conn_mod_s): you also use hash instead of an array of mod objects. (see test/add2.rb) Fri May 4 16:46:31 JST 2001 Takaaki Tateishi * misc.c (rb_ldap_apiinfo_new): new internal function * misc.c (rb_ldap_control_new): new internal function * misc.c (rb_ldap_get_apiinfo): new internal function * misc.c (rb_ldap_get_control): new internal function Sat Apr 28 08:04:25 JST 2001 Takaaki Tateishi * conn.c (rb_ldap_conn_search2_s): Conn#search2 returns an array of hash as the result of searching. Sun Apr 22 09:54:15 JST 2001 * version 0.3.5 Sat Apr 21 22:09:38 JST 2001 * conn.c (rb_ldap_conn_search_s): sorting is available. * conn.c (rb_ldap_conn_s_open): bug fix Mon Jan 29 22:40:20 JST 2001 Takaaki Tateishi * conn.c (rb_ldap_conn_set_option): LDAP_OPT_API_INFO Wed Nov 22 21:51:23 JST 2000 Takaaki Tateishi * ldap.c: add SASL constants Wed Nov 22 01:16:32 JST 2000 Takaaki Tateishi * repack (thanks Akinori MUSHA ) version 0.3.4 Tue Nov 21 16:21:57 JST 2000 Takaaki Tateishi * version 0.3.3 Tue Nov 21 16:19:40 JST 2000 Takaaki Tateishi * mod.c(rb_ldap_mod_s_new): didn't allocate enough space for 'bvals' and 'strvals'. Tue Nov 21 09:22:17 JST 2000 Takaaki Tateishi * ldap.c: add OpenLDAP TLS options Sun Nov 19 21:36:27 JST 2000 Takaaki Tateishi * conn.c (rb_ldap_conn_start_tls_s): add Conn#start_tls if you use OpenLDAP2. [experimental] * test/bind-ssl.rb: added Sun Nov 19 03:38:48 JST 2000 Takaaki Tateishi * version 0.3.2 Sun Nov 19 03:38:48 JST 2000 Takaaki Tateishi * entry.c (rb_ldap_entry_get_attributes): ber_free may cause segmentation fault when using openldap1. Sun Nov 19 02:26:52 JST 2000 Takaaki Tateishi * modify library test scripts for OpenLDAP version 1 and 2. Run test/test.sh for checking, if you have OpenLDAP. Sun Oct 29 14:26:50 JST 2000 Takaaki Tateishi * version 0.3.1 Sun Oct 29 10:59:06 JST 2000 Takaaki Tateishi * conn.c: Conn#err is added, it returns the result of the operation. * conn.c (rb_ldap_conn_perror): calls ldap_err2string if ldap_perror is not provided by the library. * conn.c: each method raises LDAP::ResultError if the result of the operation is not LDAP_SUCCESS. * conn.c (rb_ldap_get_option): allocate enough memory to the 'data'. * extconf.rb: remove -O0 option Thu Oct 26 11:50:26 JST 2000 Takaaki Tateishi * conn.c: fix some errors for NetscapeSDK Tue Oct 22 ??:??:?? JST 2000 Takaaki Tateishi * version 0.3 release Tue Oct 17 11:19:57 JST 2000 Takaaki Tateishi * ldap.c: add LDAP::LDAP_API_INFO_VERSION * extconf.rb: comile with -O0 flag * misc.c: add LDAP::APIInfo [experimental] Tue Oct 17 06:34:07 JST 2000 Takaaki Tateishi * ldap.c: add some LDAP::LDAP_OPT_XXX constant * conn.c: Conn#get_option,set_option is partially implemneted Mon Oct 16 20:43:31 JST 2000 Takaaki Tateishi * extconf.rb: --with-libxxx,--without-libxxx * conn.c: netscape sdk's ldap_perror is something wrong? if you meet bugs, execute extconf.rb with --disable-ldap-perror. * sslconn.c: I forgot replacing rb_eLDAP_ERROR with rb_eLDAP_Error. Mon Oct 16 03:08:37 JST 2000 Takaaki Tateishi * message.rb -> entry.rb * entry.c: LDAP::Message -> LDAP::Entry * conn.c: fix Conn#result2error Sun Oct 15 12:59:57 JST 2000 Takaaki Tateishi * ldap.c: add LDAP::InvalidMessageError,InvalidDataError. * rbldap.h: add Check_LDAPMSG macro. * rbldap.h: GET_LDAPMSG_DATA checks if given object is valid or not. * conn.c: Conn#search returns the error code, and a block can be given. the block argument is an instance of LDAPMessage which is valid in the block. if it is used out of the block, LDAP::InvalidMessageError is raised. (see test/test4.rb.) Sun Oct 15 04:07:08 JST 2000 Takaaki Tateishi * message.c: replace RSTRING(str)->ptr with STR2CSTR(str). Sat Oct 14 02:21:53 JST 2000 Takaaki Tateishi * version 0.2.1 released Fri Oct 13 19:16:28 JST 2000 Takaaki Tateishi * (extconf.rb) some library was not linked. * (message.rb) call free() if ldap_memfree was not present. U-Mich LDAP and OpenLDAP-1.x.x didn't provide it. (thanks atsu@@metallic.co.jp) Thu Sep 28 23:05:01 JST 2000 Takaaki Tateishi * version 0.2 released Thu Sep 28 19:54:00 JST 2000 Takaaki Tateishi * (conn.c) rb_ldap_conn_bind uses rb_ensure when a block is given. * (sslconn.c) fix SSLConn.new and SSLConn.open. Thu Sep 28 15:24:03 JST 2000 Takaaki Tateishi * (extconf.rb) check -lresolv and -lpthread. * Conn#ldap_set_option, Conn#ldap_get_option are supported.(experimental) * LDAP::LDAP_PORT, LDAP::LDAPS_PORT are added. * LDAP::LDAP_OPT_XXXXX are available if they are defined in ldap.h. Tue Sep 26 06:59:48 JST 2000 Takaaki Tateishi * LDAP::Message#to_hash is added. Mon Sep 25 07:49:44 JST 2000 Akinori MUSHA * LDAP_AUTH_METHOD_NOT_SUPPORTED is not supported by OpenLDAPv1. Mon Sep 25 07:49:13 JST 2000 Takaaki Tateishi * version 0.1 released ruby-ldap-0.9.16/saslconn.c0000644000004100000410000001455012260553634015535 0ustar www-datawww-data/* * saslconn.c * $Id: saslconn.c,v 1.25 2006/02/13 17:20:32 ianmacd Exp $ */ #include "ruby.h" #include "rbldap.h" #if defined(HAVE_SYS_TIME_H) # include #endif #if defined(HAVE_UNISTD_H) # include #endif extern VALUE rb_ldap_conn_initialize (int argc, VALUE argv[], VALUE self); extern VALUE rb_ldap_conn_rebind (VALUE self); #if defined(HAVE_LDAP_SASL_BIND_S) #include VALUE rb_ldap_indifferent_hash_aref(VALUE hash, const char *key) { VALUE symval = rb_hash_aref(hash, ID2SYM(rb_intern(key))); if (!NIL_P(symval)) { return symval; } return rb_hash_aref(hash, rb_str_new2(key)); /* this could be Qnil */ } int rb_ldap_sasl_interaction (LDAP * ld, unsigned flags, void *de, void *in) { sasl_interact_t *interact = in; VALUE options = (VALUE)de; VALUE defvalue; const char *dflt = NULL; if (ld == NULL) { return LDAP_PARAM_ERROR; } if (flags == LDAP_SASL_INTERACTIVE) { rb_raise (rb_eLDAP_Error, "interactive bind not supported."); } while (!NIL_P(options) && interact->id != SASL_CB_LIST_END) { dflt = interact->defresult; switch (interact->id) { case SASL_CB_GETREALM: if (!NIL_P(defvalue = rb_ldap_indifferent_hash_aref(options, "realm"))) { dflt = StringValuePtr(defvalue); } break; case SASL_CB_AUTHNAME: if (!NIL_P(defvalue = rb_ldap_indifferent_hash_aref(options, "authcid"))) { dflt = StringValuePtr(defvalue); } break; case SASL_CB_USER: if (!NIL_P(defvalue = rb_ldap_indifferent_hash_aref(options, "authzid"))) { dflt = StringValuePtr(defvalue); } break; default: /* Nothing. */ break; } if (dflt != NULL) { interact->result = dflt; interact->len = strlen(dflt); } interact++; } return LDAP_SUCCESS; } /* * call-seq: * conn.sasl_bind(dn=nil, mech=nil, cred=nil, sctrls=nil, cctrls=nil, sasl_options=nil) => self * conn.sasl_bind(dn=nil, mech=nil, cred=nil, sctrls=nil, cctrls=nil, sasl_options=nil) * { |conn| } => nil * * Bind an LDAP connection, using the DN, +dn+, the mechanism, +mech+, and the * credential, +cred+. * * +sctrls+ is an array of server controls, whilst +cctrls+ is an array of * client controls. * * sasl_options is a hash which should have the following keys: * * - +:authcid+ and +:authzid+ for alternate SASL authentication * - +realm+ to specify the SASL realm * * If a block is given, +self+ is yielded to the block. */ VALUE rb_ldap_conn_sasl_bind (int argc, VALUE argv[], VALUE self) { RB_LDAP_DATA *ldapdata; VALUE arg1, arg2, arg3, arg4, arg5, sasl_options, other_options = Qnil; int version; char *dn = NULL; char *mechanism = NULL; struct berval *cred = ALLOCA_N (struct berval, 1); LDAPControl **serverctrls = NULL; LDAPControl **clientctrls = NULL; /* struct berval *servercred = NULL; char *sasl_realm = NULL; char *sasl_authc_id = NULL; char *sasl_authz_id = NULL; char *sasl_secprops = NULL; struct berval passwd = { 0, NULL }; */ unsigned sasl_flags = LDAP_SASL_AUTOMATIC; Data_Get_Struct (self, RB_LDAP_DATA, ldapdata); if (!ldapdata->ldap) { if (rb_iv_get (self, "@args") != Qnil) { rb_ldap_conn_rebind (self); GET_LDAP_DATA (self, ldapdata); } else { rb_raise (rb_eLDAP_InvalidDataError, "The LDAP handler has already unbound."); } } if (ldapdata->bind) { rb_raise (rb_eLDAP_Error, "already bound."); }; switch (rb_scan_args (argc, argv, "25", &arg1, &arg2, &arg3, &arg4, &arg5, &sasl_options, &other_options)) { case 7: /* Parse through the hash. Currently there's only one option, nothing fancy needed. */ if (!NIL_P(rb_ldap_indifferent_hash_aref(other_options, "nocanon"))) { /* Inspired by the ldapsearch -N option, inspired by the code in OpenLDAP (BSD style license) in clients/tools/common.c */ ldapdata->err = ldap_set_option( ldapdata->ldap, LDAP_OPT_X_SASL_NOCANON, LDAP_OPT_ON); Check_LDAP_Result(ldapdata->err); } case 6: /* nothing. this requires credentials to be parsed first. we'll get defaults after arg-scanning */ case 5: if(!NIL_P(arg5)) clientctrls = rb_ldap_get_controls (arg5); /* down seems more likely */ case 4: if(!NIL_P(arg4)) serverctrls = rb_ldap_get_controls (arg4); /* down seems more likely */ case 3: if(!NIL_P(arg3)) { cred->bv_val = StringValueCStr (arg3); cred->bv_len = RSTRING_LEN (arg3); } /* down seems more likely */ case 2: /* don't need the cred for GSSAPI */ dn = StringValuePtr (arg1); mechanism = StringValuePtr (arg2); if (rb_iv_get (self, "@sasl_quiet") == Qtrue) sasl_flags = LDAP_SASL_QUIET; break; default: rb_bug ("rb_ldap_conn_bind_s"); } ldap_get_option (ldapdata->ldap, LDAP_OPT_PROTOCOL_VERSION, &version); if (version < LDAP_VERSION3) { version = LDAP_VERSION3; ldapdata->err = ldap_set_option (ldapdata->ldap, LDAP_OPT_PROTOCOL_VERSION, &version); Check_LDAP_Result (ldapdata->err); } /* the following works for GSSAPI, at least */ ldapdata->err = ldap_sasl_interactive_bind_s (ldapdata->ldap, dn, mechanism, serverctrls, clientctrls, sasl_flags, rb_ldap_sasl_interaction, (void*)sasl_options); if (ldapdata->err == LDAP_SASL_BIND_IN_PROGRESS) { rb_raise (rb_eNotImpError, "SASL authentication is not fully supported."); /* How can I implement this with portability? */ /* VALUE scred; scred = rb_tainted_str_new(servercred->bv_val, servercred->bv_len); */ } else { Check_LDAP_Result (ldapdata->err); ldapdata->bind = 1; } if (rb_block_given_p ()) { rb_ensure (rb_yield, self, rb_ldap_conn_unbind, self); return Qnil; } else { return self; }; } #else /* HAVE_LDAP_SASL_BIND_S */ VALUE rb_ldap_conn_sasl_bind (int argc, VALUE argv[], VALUE self) { rb_notimplement (); } #endif /* HAVE_LDAP_SASL_BIND_S */ void Init_ldap_saslconn () { rb_define_method (rb_cLDAP_Conn, "sasl_bind", rb_ldap_conn_sasl_bind, -1); } ruby-ldap-0.9.16/COPYING0000644000004100000410000000262512260553634014604 0ustar www-datawww-dataCopyright (c) 2000-2003 Takaaki Tateishi All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.