pike.git / lib / modules / Protocols.pmod / LDAP.pmod / client.pike

version» Context lines:

pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:59:   // RFC 1777,1778,1779 (version2 spec)   // RFC 1823 (v2 API)   // RFC 4510-4519 (version3 spec)   // draft-ietf-asid-ldap-c-api-00.txt (v3 API)   // RFC 2279 (UTF-8)   // RFC 2696 (paged requests)   //   // Interesting, applicable   // RFC 2307 (LDAP as network information services; draft?)    -  - #if constant(.ldap_privates) -  +    #include "ldap_globals.h"    - #if constant(SSL.Cipher.CipherAlgorithm) + #if constant(SSL.Cipher)   import SSL.Constants;   #endif      import ".";    -  + import Standards.ASN1.Types; +    // ------------------------      // ASN.1 decode macros      #define ASN1_GET_RESULTAPP(X) ((X)->elements[1]->get_tag())   #define ASN1_GET_DN(X) ((X)->elements[0]->value)   #define ASN1_GET_ATTR_ARRAY(X) (sizeof ((X)->elements) > 1 && \    (array) ((X)->elements[1]->elements))   #define ASN1_GET_ATTR_NAME(X) ((X)->elements[0]->value)   #define ASN1_GET_ATTR_VALUES(X) ((X)->elements[1]->elements->value)    - #define ASN1_RESULTCODE(X) (int)((X)->elements[1]->elements[0]->value->cast_to_int()) + #define ASN1_RESULTCODE(X) (int)((X)->elements[1]->elements[0]->value)   #define ASN1_RESULTSTRING(X) ((X)->elements[1]->elements[2]->value)   #define ASN1_RESULTREFS(X) ((X)->elements[1]->elements[3]->elements)       //! Contains the client implementation of the LDAP protocol.    //! All of the version 2 protocol features are implemented    //! but only the base parts of the version 3.       inherit .protocol;       private {
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:114:    }      //! @ignore   protected function(string:string) get_attr_decoder (string attr,    DO_IF_DEBUG (void|int nowarn))   {    if (mapping(string:mixed) attr_descr = get_attr_type_descr (attr)) {    if (function(string:string) decoder =    syntax_decode_fns[attr_descr->syntax_oid])    return decoder; - #ifdef DEBUG + #ifdef LDAP_DEBUG    else if (!get_constant_name (attr_descr->syntax_oid))    werror ("Warning: Unknown syntax %O for attribute %O - "    "binary content assumed.\n", attr_descr->syntax_oid, attr);   #endif    } - #ifdef DEBUG + #ifdef LDAP_DEBUG    else if (!nowarn && !has_suffix (attr, ";binary") && !has_value (attr, ";binary;"))    werror ("Warning: Couldn't fetch attribute description for %O - "    "binary content assumed.\n", attr);   #endif    return 0;   }   //! @endignore      protected function(string:string) get_attr_encoder (string attr)   {    if (mapping(string:mixed) attr_descr = get_attr_type_descr (attr)) {    if (function(string:string) encoder =    syntax_encode_fns[attr_descr->syntax_oid])    return encoder; - #ifdef DEBUG + #ifdef LDAP_DEBUG    else if (!get_constant_name (attr_descr->syntax_oid))    werror ("Warning: Unknown syntax %O for attribute %O - "    "binary content assumed.\n", attr_descr->syntax_oid, attr);   #endif    } - #ifdef DEBUG + #ifdef LDAP_DEBUG    else if (!has_suffix (attr, ";binary") && !has_value (attr, ";binary;"))    werror ("Warning: Couldn't fetch attribute description for %O - "    "binary content assumed.\n", attr);   #endif    return 0;   }      typedef string|Charset.DecodeError|    array(string|Charset.DecodeError) ResultAttributeValue;   
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:340:    ent->dn = dn;    }       //!    //! You can't create instances of this object yourself.    //! The only way to create it is via a search of a LDAP server.    object|int create(array(object) entries, int stuff, int flags) {    // entries: array of der decoded entries, but WITHOUT LDAP PDU !!!    // stuff: 1=bind result; ...    -  this_program::flags = flags; +  this::flags = flags;       // Note: Might do additional schema queries to the server while    // decoding the result. That means possible interleaving problem    // if search() is extended to not retrieve the complete reply at    // once.       if (!sizeof (entries)) {    seterr (LDAP_LOCAL_ERROR);    THROW(({"LDAP: Internal error.\n",backtrace()}));    return -ldap_errno;    } -  DWRITE(sprintf("result.create: %O\n",entries[-1])); +  DWRITE("result.create: %O\n", entries[-1]);       // The last element of 'entries' is result itself    resultcode = ASN1_RESULTCODE (entries[-1]); -  DWRITE(sprintf("result.create: code=%d\n",resultcode)); +  DWRITE("result.create: code=%d\n", resultcode);    resultstring = ASN1_RESULTSTRING (entries[-1]);    if (resultstring == "")    resultstring = 0;    else if (ldap_version >= 3)    if (mixed err = catch (resultstring = utf8_to_string (resultstring))) -  DWRITE (sprintf ("Failed to decode result string %O: %s", -  resultstring, describe_error (err))); -  DWRITE(sprintf("result.create: str=%O\n",resultstring)); +  DWRITE ("Failed to decode result string %O: %s", +  resultstring, describe_error (err)); +  DWRITE("result.create: str=%O\n", resultstring);   #ifdef V3_REFERRALS    // referral (v3 mode)    if(resultcode == 10) {    referrals = ({});    foreach(ASN1_RESULTREFS (entries[-1]), object ref1)    referrals += ({ ref1->value }); -  DWRITE(sprintf("result.create: refs=%O\n",referrals)); +  DWRITE("result.create: refs=%O\n", referrals);    }   #endif -  DWRITE(sprintf("result.create: elements=%d\n",sizeof (entries))); - #if 0 -  DWRITE(sprintf("result.create: entries=%O\n", entries[..<1])); - #endif +  DWRITE("result.create: elements=%d\n", sizeof(entries));       entry = decode_entries (entries[..<1]);      #if 0    // Context specific proccessing of 'entries'    switch(stuff) { -  case 1: DWRITE("result.create: stuff=1\n"); +  case 1: +  DWRITE("result.create: stuff=1\n");    break; -  default: DWRITE(sprintf("result.create: stuff=%d\n", stuff)); -  +  default: +  DWRITE("result.create: stuff=%d\n", stuff); +  break;    }   #endif       return this; -  +     }       //!    //! Returns the error number in the search result.    //!    //! @seealso    //! @[error_string], @[server_error_string]    int error_number() { return resultcode; }       //!
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:489:    //!    //! @note    //! In Pike 7.6 and earlier, the special @expr{"dn"@} entry was    //! incorrectly returned in UTF-8 encoded form for LDAPv3    //! connections.    //!    //! @seealso    //! @[fetch_all]    ResultEntry fetch(int|void idx)    { -  -  if (!zero_type (idx)) actnum = idx; +  if (!undefinedp (idx)) actnum = idx;    if (actnum >= num_entries() || actnum < 0) return 0;       if (ldap_version < 3)    return entry[actnum];       ResultEntry ent = entry[actnum];       if (actnum == first_undecoded_entry) {    decode_entry (ent);    first_undecoded_entry++;
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:631:    return -ldap_errno;    }    return 0;    }       //! Several information about code itself and about active connection too    mapping info;      #ifndef PARSE_RFCS    //! @decl void create() -  //! @decl void create(string url) -  //! @decl void create(string url, object context) +  //! @decl void create(string|mapping(string:mixed) url) +  //! @decl void create(string|mapping(string:mixed) url, object context)    //!    //! Create object. The first optional argument can be used later    //! for subsequence operations. The second one can specify    //! TLS context of connection. The default context only allows    //! 128-bit encryption methods, so you may need to provide your    //! own context if your LDAP server supports only export encryption.    //!    //! @param url    //! LDAP server URL on the form -  //! @expr{"ldap://hostname/basedn?attrlist?scope?ext"@}. See RFC -  //! 2255. It can also be a mapping as returned by -  //! @[Protocol.LDAP.parse_ldap_url]. +  //! @expr{"ldap://hostname/basedn?attrlist?scope?ext"@}. See @rfc{2255@}. +  //! It can also be a mapping as returned by @[Protocol.LDAP.parse_ldap_url].    //!    //! @param context    //! TLS context of connection    //!    //! @seealso    //! @[LDAP.client.bind], @[LDAP.client.search]    void create(string|mapping(string:mixed)|void url, object|void context)    {       info = ([ "code_revision" :
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:668: Inside #if undefined(PARSE_RFCS)
   if(!url || !sizeof(url))    url = LDAP_DEFAULT_URL;       if (mappingp (url))    lauth = url;    else    lauth = parse_ldap_url(url);       if(!stringp(lauth->scheme) ||    ((lauth->scheme != "ldap") - #if constant(SSL.Cipher.CipherAlgorithm) + #if constant(SSL.Cipher)    && (lauth->scheme != "ldaps")   #endif    )) {    THROW(({"Unknown scheme in server URL.\n",backtrace()}));    }       if(!lauth->host)    lauth += ([ "host" : LDAP_DEFAULT_HOST ]);    if(!lauth->port)    lauth += ([ "port" : lauth->scheme == "ldap" ? LDAP_DEFAULT_PORT : LDAPS_DEFAULT_PORT ]);    - #if constant(SSL.Cipher.CipherAlgorithm) + #if constant(SSL.Cipher)    if(lauth->scheme == "ldaps" && !context) { -  context = SSL.context(); -  // Allow only strong crypto -  context->preferred_suites = ({ -  SSL_rsa_with_idea_cbc_sha, -  SSL_rsa_with_rc4_128_sha, -  SSL_rsa_with_rc4_128_md5, -  SSL_rsa_with_3des_ede_cbc_sha, -  }); +  context = SSL.Context();    }   #endif       Stdio.File low_fd = Stdio.File();       if(!(low_fd->connect(lauth->host, lauth->port))) {    //errno = ldapfd->errno();    seterr (LDAP_SERVER_DOWN, strerror (low_fd->errno()));    //ldapfd->destroy();    //ldap=0;    //ok = 0;    //if(con_fail)    // con_fail(this, @extra_args);    ERROR ("Failed to connect to LDAP server: %s\n", ldap_rem_errstr);    }    - #if constant(SSL.Cipher.CipherAlgorithm) + #if constant(SSL.Cipher)    if(lauth->scheme == "ldaps") { -  context->random = Crypto.Random.random_string; -  ::create(SSL.sslfile(low_fd, context, 1,1)); +  SSL.File ssl_fd = SSL.File(low_fd, context); +  ssl_fd->set_blocking(); // NB: SSL.File defaults to non-blocking mode. +  if (!ssl_fd->connect()) { +  ERROR("Failed to connect to LDAPS server.\n"); +  } +  ::create(ssl_fd);    info->tls_version = ldapfd->version;    } else    ::create(low_fd);   #else    if(lauth->scheme == "ldaps") {    THROW(({"LDAP: LDAPS is not available without SSL support.\n",backtrace()}));    }    else    ::create(low_fd);   #endif       DWRITE("client.create: connected!\n");    -  DWRITE(sprintf("client.create: remote = %s\n", low_fd->query_address())); +  DWRITE("client.create: remote = %s\n", low_fd->query_address());    DWRITE_HI("client.OPEN: " + lauth->host + ":" + (string)(lauth->port) + " - OK\n");       reset_options();    } // create   #endif      void reset_options()   //! Resets all connection options, such as the scope and the base DN,   //! to the defaults determined from the LDAP URL when the connection   //! was created.
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:750:    last_rv = 0;   }       private mixed send_bind_op(string name, string password) {    // Simple BIND operation       object msgval, vers, namedn, auth;    string pass = password;    password = "censored";    -  vers = Standards.ASN1.Types.asn1_integer(ldap_version); -  namedn = Standards.ASN1.Types.asn1_octet_string(name); +  vers = Integer(ldap_version); +  namedn = OctetString(name);    auth = ASN1_CONTEXT_OCTET_STRING(0, pass);    // SASL credentials ommited       msgval = ASN1_APPLICATION_SEQUENCE(0, ({vers, namedn, auth}));       return do_op(msgval);    }       private mixed send_starttls_op(object|void context) {       object msgval; - #if constant(SSL.Cipher.CipherAlgorithm) + #if constant(SSL.Cipher)       // can we do this now?    if(ldapfd->context)    {    THROW(({"LDAP: TLS/SSL already established.\n",backtrace()}));    }       // NOTE: should we be on the lookout for requests in flight?          -  msgval = ASN1_APPLICATION_SEQUENCE(23, ({Standards.ASN1.Types.OctetString("1.3.6.1.4.1.1466.20037")})); +  msgval = ASN1_APPLICATION_SEQUENCE(23, ({OctetString("1.3.6.1.4.1.1466.20037")}));       do_op(msgval);    int result = ASN1_RESULTCODE(.ldap_privates.ldap_der_decode (readbuf));    if(result!=0) return 0;    // otherwise, we can try to negotiate.    if(!context)    { -  context = SSL.context(); -  // Allow only strong crypto -  context->preferred_suites = ({ -  SSL_rsa_with_idea_cbc_sha, -  SSL_rsa_with_rc4_128_sha, -  SSL_rsa_with_rc4_128_md5, -  SSL_rsa_with_3des_ede_cbc_sha, -  }); +  context = SSL.Context();    }    object _f = ldapfd; -  ldapfd=SSL.sslfile(_f, context, 1, 1); -  return 1; +  ldapfd = SSL.File(_f, context); +  return ldapfd->connect();   #endif    return 0;    }       //! Requests that a SSL/TLS session be negotiated on the connection.    //! If the connection is already secure, this call will fail.    //!    //! @param context    //! an optional SSL.context object to provide to the    //! SSL/TLS connection client.    //!    //! Returns @expr{1@} on success, @expr{0@} otherwise.    //! -  int start_tls (void|SSL.context context) { -  +  int start_tls (void|SSL.Context context) { + #if constant(SSL.Cipher)    if(ldap_version < 3)    {    seterr (LDAP_PROTOCOL_ERROR);    THROW(({"LDAP: Unknown/unsupported protocol version.\n",backtrace()}));    return -ldap_errno;    }       return send_starttls_op(context||UNDEFINED);       return 1; -  + #else +  return 0; + #endif    } // start_tls       //! @decl int bind()    //! @decl int bind(string dn, string password)    //! @decl int bind(string dn, string password, int version)    //!    //! Authenticates connection to the direcory.    //!    //! First form uses default value previously entered in create.    //!
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:891:    THROW(({error_string()+"\n",backtrace()}));    return 0;    }       bound_dn = md5_password = 0;    last_rv = SIMPLE_RESULT (raw, 1, 0);    if (!last_rv->error_number()) {    bound_dn = dn;    md5_password = Crypto.MD5.hash (pass);    } -  DWRITE_HI(sprintf("client.BIND: %s\n", last_rv->error_string())); +  DWRITE_HI("client.BIND: %s\n", last_rv->error_string());    seterr (last_rv->error_number(), last_rv->error_string());    return !!bound_dn;       } // bind          private int send_unbind_op() {    // UNBIND operation       writemsg(ASN1_APPLICATION_OCTET_STRING(2, ""));       //ldap::close();       return 1;    }      #if 0 -  void destroy() { +  protected void _destruct() {       //send_unbind_op();       // Hazard area: General confusion error. /mast    //destruct(this);    }   #endif       //!    //! Unbinds from the directory and close the connection.
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:969:    return 0;    if(ldap_version == 3) {    dn = string_to_utf8(dn);    }    if(intp(raw = send_op_withdn(10, dn))) {    THROW(({error_string()+"\n",backtrace()}));    return 0;    }       last_rv = SIMPLE_RESULT (raw, 0, 0); -  DWRITE_HI(sprintf("client.DELETE: %s\n", last_rv->error_string())); +  DWRITE_HI("client.DELETE: %s\n", last_rv->error_string());    seterr (last_rv->error_number(), last_rv->error_string());    return !last_rv->error_number();       } // delete       private int|string send_compare_op(string dn, string attr, string value) {    // COMPARE       object msgval;       msgval = ASN1_APPLICATION_SEQUENCE(14, -  ({ Standards.ASN1.Types.asn1_octet_string(dn), -  Standards.ASN1.Types.asn1_sequence( -  ({ Standards.ASN1.Types.asn1_octet_string(attr), -  Standards.ASN1.Types.asn1_octet_string(value) -  })) +  ({ OctetString(dn), +  Sequence( ({ OctetString(attr), OctetString(value) }) )    })    );       return do_op(msgval);    }          //!    //! Compares an attribute value with one in the directory.    //!
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1044:    dn = string_to_utf8(dn);    if (function(string:string) encoder = get_attr_encoder (attr))    value = encoder (value);    }    if(intp(raw = send_compare_op(dn, attr, value))) {    THROW(({error_string()+"\n",backtrace()}));    return 0;    }       last_rv = SIMPLE_RESULT (raw, 0, 0); -  DWRITE_HI(sprintf("client.COMPARE: %s\n", last_rv->error_string())); +  DWRITE_HI("client.COMPARE: %s\n", last_rv->error_string());    seterr (last_rv->error_number(), last_rv->error_string());    return last_rv->error_number() == LDAP_COMPARE_TRUE;       } // compare       private int|string send_add_op(string dn, mapping(string:array(string)) attrs) {    // ADD       object msgval;    string atype;    array(object) oatt = ({});       foreach(indices(attrs), atype) {    string aval;    array(object) ohlp = ({});       foreach(values(attrs[atype]), aval) -  ohlp += ({Standards.ASN1.Types.asn1_octet_string(aval)}); -  oatt += ({Standards.ASN1.Types.asn1_sequence( -  ({Standards.ASN1.Types.asn1_octet_string(atype), -  Standards.ASN1.Types.asn1_set(ohlp) +  ohlp += ({OctetString(aval)}); +  oatt += ({Sequence( +  ({OctetString(atype), +  Set(ohlp)    }))    });    }       msgval = ASN1_APPLICATION_SEQUENCE(8, -  ({Standards.ASN1.Types.asn1_octet_string(dn), -  Standards.ASN1.Types.asn1_sequence(oatt) -  })); +  ({ OctetString(dn), Sequence(oatt) }));       return do_op(msgval);    }          //! The Add Operation allows a client to request the addition    //! of an entry into the directory    //!    //! @param dn    //! The Distinguished Name of the entry to be added.
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1122:    foreach (indices(attrs), string attr)    if (function(string:string) encoder = get_attr_encoder (attr))    attrs[attr] = map (attrs[attr], encoder);    }    if(intp(raw = send_add_op(dn, attrs))) {    THROW(({error_string()+"\n",backtrace()}));    return 0;    }       last_rv = SIMPLE_RESULT (raw, 0, 0); -  DWRITE_HI(sprintf("client.ADD: %s\n", last_rv->error_string())); +  DWRITE_HI("client.ADD: %s\n", last_rv->error_string());    seterr (last_rv->error_number(), last_rv->error_string());    return !last_rv->error_number();       } // add      protected mapping(string:array(string)) simple_read (string object_name,    object filter,    array attrs)   // Makes a base object search for object_name. The result is returned   // as a mapping where the attribute types have been lowercased and the
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1188:   //! @note   //! This function intentionally does not try to simplify the return   //! values for single-valued attributes (c.f.   //! @[Protocols.LDAP.SEARCH_MULTIVAL_ARRAYS_ONLY]). That since (at   //! least) Microsoft AD has a bunch of attributes in the root DSE   //! that they don't bother to provide schema entries for. The return   //! value format wouldn't be reliable if they suddenly change that.   {    attr = lower_case (attr);    -  if (!root_dse || zero_type (root_dse[attr])) { +  if (!root_dse || !has_index (root_dse, attr)) {    PROFILE("get_root_dse_attr", {       multiset(string) attrs = root_dse ? (<>) :    // Get a bunch of attributes in one go.    (<    // Request all standard operational attributes (RFC 2252,    // section 5.1). Some of them are probably not applicable    // in the root DSE, but better safe than sorry.    "createtimestamp",    "modifytimestamp",
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1244:    }    });    }       return root_dse[attr];   }      protected object make_control (string control_type, void|string value,    void|int critical)   { -  array(object) seq = ({Standards.ASN1.Types.asn1_octet_string (control_type), -  ASN1_BOOLEAN (critical)}); -  if (value) seq += ({Standards.ASN1.Types.asn1_octet_string (value)}); -  return Standards.ASN1.Types.asn1_sequence (seq); +  array(object) seq = ({OctetString (control_type), +  Boolean (critical)}); +  if (value) seq += ({OctetString (value)}); +  return Sequence (seq);   }      protected multiset(string) supported_controls;      multiset(string) get_supported_controls()   //! Returns a multiset containing the controls supported by the   //! server. They are returned as object identifiers on string form.   //! A working connection is assumed.   //!   //! @seealso
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1324:    {    // SEARCH    // limitations: !!! sizelimit and timelimit should be unsigned int !!!       array(object) ohlp;       ohlp = ({filter});    if (arrayp(attrs)) { //explicitly defined attributes    array(object) o2 = ({});    foreach(attrs, string s2) -  o2 += ({Standards.ASN1.Types.asn1_octet_string(s2)}); -  ohlp += ({Standards.ASN1.Types.asn1_sequence(o2)}); +  o2 += ({OctetString(s2)}); +  ohlp += ({Sequence(o2)});    } else -  ohlp += ({Standards.ASN1.Types.asn1_sequence(({}))}); +  ohlp += ({Sequence(({}))});       return ASN1_APPLICATION_SEQUENCE(3, -  ({ Standards.ASN1.Types.asn1_octet_string(basedn), -  ASN1_ENUMERATED(scope), -  ASN1_ENUMERATED(deref), -  Standards.ASN1.Types.asn1_integer(sizelimit), -  Standards.ASN1.Types.asn1_integer(timelimit), -  ASN1_BOOLEAN(attrsonly ? -1 : 0), +  ({ OctetString(basedn), +  Enumerated(scope), +  Enumerated(deref), +  Integer(sizelimit), +  Integer(timelimit), +  Boolean(attrsonly ? -1 : 0),    @ohlp    })) ;    }       //! Search LDAP directory.    //!    //! @param filter    //! Search filter to override the one from the LDAP URL. It's -  //! either a string with the format specified in RFC 2254, or an +  //! either a string with the format specified in @rfc{2254@}, or an    //! object returned by @[Protocols.LDAP.make_filter].    //!    //! @param attrs    //! The array of attribute names which will be returned by server    //! for every entry.    //!    //! @param attrsonly    //! This flag causes server return only the attribute types (aka    //! names) but not their values. The values will instead be empty    //! arrays or - if @[Protocols.LDAP.SEARCH_MULTIVAL_ARRAYS_ONLY]
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1408:    //! @[Protocols.LDAP.ldap_encode_string], @[Protocols.LDAP.make_filter]    result|int search (string|object|void filter, array(string)|void attrs,    int|void attrsonly,    void|mapping(string:array(int|string)) controls,    void|int flags) {       int id;    object entry;    array(object) entries = ({});    -  DWRITE_HI(sprintf ("client.SEARCH: %O\n", filter)); +  DWRITE_HI("client.SEARCH: %O\n", filter);    if (chk_ver())    return 0;    if (chk_binded())    return 0;       if (!objectp (filter))    if (mixed err = catch {    if (!filter)    filter = get_default_filter();    else
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1464: Inside #if 0
   // LDAP_SERVER_DOMAIN_SCOPE_OID    // "Tells server not to generate referrals" (NtLdap.h)    common_controls += ({make_control (LDAP_SERVER_DOMAIN_SCOPE_OID)});    }   #endif      #ifdef ENABLE_PAGED_SEARCH    get_supported_controls();   #endif    -  object cookie = Standards.ASN1.Types.asn1_octet_string(""); +  object cookie = OctetString("");    do {    PROFILE("send_search_op", {    array ctrls = common_controls;    IF_ELSE_PAGED_SEARCH (    if (supported_controls[LDAP_PAGED_RESULT_OID_STRING]) {    // LDAP Control Extension for Simple Paged Results Manipulation    // RFC 2696.    ctrls += ({make_control (    LDAP_PAGED_RESULT_OID_STRING, -  Standards.ASN1.Types.asn1_sequence( +  Sequence(    ({    // size -  Standards.ASN1.Types.asn1_integer(0x7fffffff), +  Integer(0x7fffffff),    cookie, // cookie    }))->get_der(),    sizeof(cookie->value))});    },);    object controls;    if (sizeof(ctrls)) { -  controls = .ldap_privates.asn1_sequence(0, ctrls); +  controls = ASN1_CONTEXT_SEQUENCE(0, ctrls);    }       string|int raw;    if(intp(raw = do_op(search_request, controls))) {    THROW(({error_string()+"\n",backtrace()}));    return 0;    }    entry = .ldap_privates.ldap_der_decode (raw);    });   
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1566:       },);    } while (cookie);       PROFILE("result", last_rv = result (entries, 0, flags));    if(objectp(last_rv))    seterr (last_rv->error_number(), last_rv->error_string());    //if (rv->error_number() || !rv->num_entries()) // if error or entries=0    // rv = rv->error_number();    -  DWRITE_HI(sprintf("client.SEARCH: %s (entries: %d)\n", -  last_rv->error_string(), last_rv->num_entries())); +  DWRITE_HI("client.SEARCH: %s (entries: %d)\n", +  last_rv->error_string(), last_rv->num_entries());    return last_rv;       } // search      mapping(string:string|array(string)) read (    string object_name,    void|string filter,    void|array(string) attrs,    void|int attrsonly,    void|mapping(string:array(int|string)) controls,
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1622:    }       object ctrls;    if (controls) {    array(object) control_list = allocate (sizeof (controls));    int i;    foreach (controls; string type; array(int|string) data)    control_list[i++] =    make_control (type, [string] data[1], [int] data[0]);    if (sizeof (control_list)) -  ctrls = .ldap_privates.asn1_sequence(0, control_list); +  ctrls = ASN1_CONTEXT_SEQUENCE(0, control_list);    }       object entry;    PROFILE ("send_get_op", {    string|int raw;    if(intp(raw = do_op(search_request, ctrls))) {    THROW(({error_string()+"\n",backtrace()}));    return 0;    }    entry = .ldap_privates.ldap_der_decode (raw);
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1755:    case "sub": scope = SCOPE_SUB; break;    case "one": scope = SCOPE_ONE; break;    case "base": scope = SCOPE_BASE; break;    default: ERROR ("Invalid scope %O.\n", scope);    }    else    if (!(<SCOPE_BASE, SCOPE_ONE, SCOPE_SUB>)[scope])    ERROR ("Invalid scope %O.\n", scope);       ldap_scope = scope; -  DWRITE_HI("client.SET_SCOPE = " + (string)scope + "\n"); +  DWRITE_HI("client.SET_SCOPE = %O\n", scope);    return old_scope;    }      //! Return the currently set scope as a string @expr{"base"@},   //! @expr{"one"@}, or @expr{"sub"@}.   string get_scope()    {return ([SCOPE_BASE: "base", SCOPE_ONE: "one", SCOPE_SUB: "sub"])[ldap_scope];}       //! @param option_type    //! LDAP_OPT_xxx    //! @param value    //! new value for option    int set_option (int opttype, int value) {    -  DWRITE_HI("client.SET_OPTION: " + (string)opttype + " = " + (string)value + "\n"); +  DWRITE_HI("client.SET_OPTION: %O = %O\n", opttype, value);    switch (opttype) {    case 1: // LDAP_OPT_DEREF    //if (intp(value))    ldap_deref = value;    //else    // return -1;    break;    case 2: // LDAP_OPT_SIZELIMIT    //if (intp(value))    ldap_sizelimit = value;
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1803:          return 0;    }       //! @param option_type    //! LDAP_OPT_xxx    int get_option (int opttype) {       -  DWRITE_HI("client.GET_OPTION: " + (string)opttype + "\n"); +  DWRITE_HI("client.GET_OPTION: %O\n", opttype);    switch (opttype) {    case 1: // LDAP_OPT_DEREF    return ldap_deref;    case 2: // LDAP_OPT_SIZELIMIT    return ldap_sizelimit;    case 3: // LDAP_OPT_TIMELIMIT    return ldap_timelimit;    case 4: // LDAP_OPT_REFERRALS    }   
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1837:    object o, msgval;    string atype;    array(object) oatt = ({}), attrarr;          foreach(indices(attropval), atype) {    if(!intp((attropval[atype])[0]))    return seterr(LDAP_PROTOCOL_ERROR);    attrarr = ({});    for(int ix=1; ix<sizeof(attropval[atype]); ix++) -  attrarr += ({Standards.ASN1.Types.asn1_octet_string( -  (attropval[atype])[ix])}); +  attrarr += ({ OctetString(attropval[atype][ix]) });   // if(sizeof(attrarr)) // attributevalue ? -  o = Standards.ASN1.Types.asn1_sequence( -  ({Standards.ASN1.Types.asn1_octet_string(atype), -  Standards.ASN1.Types.asn1_set(attrarr) -  })); +  o = Sequence( ({OctetString(atype), Set(attrarr) }));   // else   // o = Standards.ASN1.Encode.asn1_sequence(   // Standards.ASN1.Encode.asn1_octet_string(atype)); -  oatt += ({Standards.ASN1.Types.asn1_sequence( -  ({ASN1_ENUMERATED((attropval[atype])[0]), -  o -  }))}); +  oatt += ({ Sequence( ({Enumerated((attropval[atype])[0]), o})) });    } //foreach       msgval = ASN1_APPLICATION_SEQUENCE(6, -  ({ Standards.ASN1.Types.asn1_octet_string(dn), -  Standards.ASN1.Types.asn1_sequence(oatt) -  })); +  ({ OctetString(dn), Sequence(oatt) }));       return do_op(msgval);    }       private int|string send_modifydn_op(string dn, string newrdn,    int deleteoldrdn, string newsuperior) {       object msgval; -  array seq=({ Standards.ASN1.Types.asn1_octet_string(dn), -  Standards.ASN1.Types.asn1_octet_string(newrdn), -  Standards.ASN1.Types.asn1_boolean(deleteoldrdn) +  array seq=({ +  OctetString(dn), +  OctetString(newrdn), +  Boolean(deleteoldrdn)    });    if(newsuperior) -  seq+=({Standards.ASN1.Types.asn1_octet_string(newsuperior)}); +  seq+=({ OctetString(newsuperior)});       msgval = ASN1_APPLICATION_SEQUENCE(12, seq);       return do_op(msgval);    }       //! The Modify DN Operation allows a client to change the leftmost    //! (least significant) component of the name of an entry in the directory,    //! or to move a subtree of entries to a new location in the directory.    //!
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1924:    dn = string_to_utf8(dn);    newrdn = string_to_utf8(newrdn);    if(newsuperior) newsuperior = string_to_utf8(newsuperior);    }    if(intp(raw = send_modifydn_op(dn, newrdn, deleteoldrdn, newsuperior))) {    THROW(({error_string()+"\n",backtrace()}));    return 0;    }       last_rv = SIMPLE_RESULT (raw, 0, 0); -  DWRITE_HI(sprintf("client.MODIFYDN: %s\n", last_rv->error_string())); +  DWRITE_HI("client.MODIFYDN: %s\n", last_rv->error_string());    seterr (last_rv->error_number(), last_rv->error_string());    return !last_rv->error_number();       } //modifydn       //! The Modify Operation allows a client to request that a modification    //! of an entry be performed on its behalf by a server.    //!    //! @param dn    //! The distinguished name of modified entry.
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:2000:    op[i] = encoder (op[i]);    attropval[attr] = op;    }    }    if(intp(raw = send_modify_op(dn, attropval))) {    THROW(({error_string()+"\n",backtrace()}));    return 0;    }       last_rv = SIMPLE_RESULT (raw, 0, 0); -  DWRITE_HI(sprintf("client.MODIFY: %s\n", last_rv->error_string())); +  DWRITE_HI("client.MODIFY: %s\n", last_rv->error_string());    seterr (last_rv->error_number(), last_rv->error_string());    return !last_rv->error_number();       } // modify       //! Gets referrals.    //!    //! @returns    //! Returns array of referrals or @expr{0@}.    array|int get_referrals() {
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:2330:    "dsaoperation": "dSAOperation"    ]),    "": "qdstrings"   ]);      protected mapping(string:mapping(string:mixed)) attr_type_descrs;      mapping(string:mixed) get_attr_type_descr (string attr, void|int standard_attrs)   //! Returns the attribute type description for the given attribute,   //! which includes the name, object identifier, syntax, etc (see - //! section 4.2 in RFC 2252 for details). + //! @rfc{2252:4.2@} for details).   //!   //! This might do a query to the server, but results are cached.   //!   //! @param attr   //! The name of the attribute. Might also be the object identifier   //! on string form.   //!   //! @param standard_attrs   //! Flag that controls how the known standard attributes stored in   //! @[Protocols.LDAP] are to be used:
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:2390:   //! oid of it. Note that the attribute description from the   //! referenced type always is merged with the current one to make   //! the returned description complete.   //! @member string "EQUALITY"   //! The value is the name or oid of a matching rule.   //! @member string "ORDERING"   //! The value is the name or oid of a matching rule.   //! @member string "SUBSTR"   //! The value is the name or oid of a matching rule.   //! @member string "syntax_oid" - //! The value is the oid of the syntax (RFC 2252, section 4.3.2). + //! The value is the oid of the syntax (@rfc{2252:4.3.2@}).   //! (This is extracted from the @expr{"SYNTAX"@} term.)   //! @member string "syntax_len"   //! Optional suggested minimum upper bound of the number of   //! characters in the attribute (or bytes if the attribute is   //! binary). (This is extracted from the @expr{"SYNTAX"@} term.)   //! @member string "SINGLE-VALUE"   //! Flag. Default multi-valued.   //! @member string "COLLECTIVE"   //! Flag. Default not collective.   //! @member string "NO-USER-MODIFICATION"
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:2468:    string sup = lower_case (descr->SUP);    mapping(string:mixed) sup_descr =    attr_type_descrs[sup] ||    (standard_attrs != 1 && _standard_attr_type_descrs[sup]);    if (!sup_descr)    ERROR ("Inconsistency in schema: "    "Got SUP reference to unknown attribute: %O\n", descr);    if (sup_descr->SUP)    complete (sup_descr);    foreach (indices (sup_descr), string term) -  if (zero_type (descr[term])) +  if (!has_index (descr, term))    descr[term] = sup_descr[term];    };    foreach (incomplete, mapping(string:mixed) descr)    complete (descr);    }    }       return attr_type_descrs[attr];   }   
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:2542: Inside #if defined(PARSE_RFCS)
   write (" %O: %O,\n", term, val);    }    }    }    write ("]);\n");    }    }   }      #endif -  - #else - constant this_program_does_not_exist=1; - #endif +