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

version» Context lines:

pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1:   #pike __REAL_VERSION__      // LDAP client protocol implementation for Pike.   // - // $Id: client.pike,v 1.84 2005/03/23 18:20:45 mast Exp $ + // $Id: client.pike,v 1.85 2005/03/23 19:23:03 mast Exp $   //   // Honza Petrous, hop@unibase.cz   //   // ----------------------------------------------------------------------   //   // History:   //   // v0.0 1998-05-25 Starting up!   // v1.0 1998-06-21 Core functions (open, bind, unbind, delete, add,   // compare, search), only V2 operations,
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:328:    //! @param index    //! Optional argument can be used for direct access    //! to the entry other then currently pointed by cursor.    //!    //! @returns    //! The return value is a mapping describing the entry:    //!    //! @mapping    //! @member string attribute    //! An attribute in the entry. The value is an array containing -  //! the returned attribute value(s) on string form. It may be -  //! an empty array if only the attribute types were requested -  //! or if all values were excluded. +  //! the returned attribute value(s) on string form.    //!    //! @member string "dn"    //! This special entry contains the object name of the entry as    //! a distinguished name.    //! @endmapping    //!    //! Zero is returned if the cursor is outside the valid range of    //! entries.    //!    //! @note
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:482: Inside #if undefined(PARSE_RFCS)
   //! 2255.    //!    //! @param context    //! TLS context of connection    //!    //! @seealso    //! @[LDAP.client.bind], @[LDAP.client.search]    void create(string|void url, object|void context)    {    -  info = ([ "code_revision" : ("$Revision: 1.84 $"/" ")[1] ]); +  info = ([ "code_revision" : ("$Revision: 1.85 $"/" ")[1] ]);       if(!url || !sizeof(url))    url = LDAP_DEFAULT_URL;       lauth = parse_url(url);       if(!stringp(lauth->scheme) ||    ((lauth->scheme != "ldap")   #if constant(SSL.Cipher.CipherAlgorithm)    && (lauth->scheme != "ldaps")
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:939:    return 0;    }       last_rv = result(({raw}));    DWRITE_HI(sprintf("client.ADD: %s\n", last_rv->error_string()));    seterr(last_rv->error_number());    return !last_rv->error_number();       } // add    - static mapping(string:array(string)) simple_base_query (string object_name, + static mapping(string:array(string)) simple_read (string object_name,    string 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   // string values are unprocessed.   {    object|int search_request =    make_search_op(object_name, 0, 0, 0, 0, 0, filter, attrs);    //werror("search_request: %O\n", search_request);   
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1021:    "namingcontexts",    "altserver",    "supportedextension",    "supportedcontrol",    "supportedsaslmechanisms",    "supportedldapversion",    >);    attrs[attr] = 1;       mapping(string:array(string)) res = -  simple_base_query ("", "(objectClass=*)", indices (attrs)); +  simple_read ("", "(objectClass=*)", indices (attrs));       foreach (indices (res), string attr)    // Microsoft AD has several attributes in its root DSE that    // they haven't bothered to include in their schema. Send    // the nowarn flag to get_attr_encoder to avoid complaints    // about that.    if (function(string:string) decoder =    get_attr_decoder (attr, DO_IF_DEBUG (1)))    res[attr] = map (res[attr], decoder);   
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1364:    //!    //! @returns    //! Returns object @[LDAP.client.result] on success, @expr{0@}    //! otherwise.    //!    //! @note    //! The API change: the returning code was changed in Pike 7.3+    //! to follow his logic better.    //!    //! @seealso -  //! @[result], @[result.fetch], @[get_supported_controls], +  //! @[result], @[result.fetch], @[read], @[get_supported_controls],    //! @[Protocols.LDAP.quote_filter_value]    object|int search (string|void filter, array(string)|void attrs,    int|void attrsonly,    void|mapping(string:array(int|string)) controls,    void|int flags) {       int id,nv;    mixed raw;    array(string) rawarr = ({});   
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1526:    seterr (last_rv->error_number());    //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()));    return last_rv;       } // search    + mapping(string:array(string)) read (string object_name, +  void|string filter, +  void|array(string) attrs, +  void|int attrsonly, +  void|mapping(string:array(int|string)) controls, +  void|int flags) + //! Reads a specified object in the LDAP server. @[object_name] is the + //! distinguished name for the object. The rest of the arguments are + //! the same as to @[search]. + //! + //! The default filter and attributes that might have been set in the + //! LDAP URL doesn't affect this call. If @[filter] isn't set then + //! @expr{"(objectClass=*)"@} is used. + //! + //! @returns + //! Returns a mapping of the requested attributes. It has the same + //! form as the response from @[result.fetch]. + //! + //! @seealso + //! @[search] + { +  if (chk_ver()) +  return 0; +  if (chk_binded()) +  return 0; +  if(ldap_version == 3) { +  object_name = string_to_utf8 (object_name); +  if (filter) filter = string_to_utf8(filter); +  }    -  +  object|int search_request = +  make_search_op (object_name, 0, ldap_deref, +  ldap_sizelimit, ldap_timelimit, attrsonly, +  filter || "(objectClass=*)", attrs); +  +  if(intp(search_request)) { +  THROW(({error_string()+"\n",backtrace()})); +  return 0; +  } +  +  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); +  } +  +  string|int raw; +  PROFILE ("send_get_op", { +  if(intp(raw = do_op(search_request, ctrls))) { +  THROW(({error_string()+"\n",backtrace()})); +  return 0; +  } +  }); +  +  array(string) rawarr; +  PROFILE("rawarr++", { +  rawarr = ({raw}); +  while (ASN1_DECODE_RESULTAPP(raw) != 5) { +  // NB: The msgid stuff is defunct in readmsg, so we can +  // just as well pass a zero there. :P +  PROFILE("readmsg", raw = readmsg(0)); +  if (intp(raw)) { +  THROW(({error_string()+"\n",backtrace()})); +  return 0; +  } +  rawarr += ({raw}); +  } // while +  }); +  +  PROFILE ("result", last_rv = result (rawarr, 0, flags)); +  seterr (last_rv->error_number()); +  +  if (ldap_errno != LDAP_SUCCESS) return 0; +  return last_rv->fetch(); + } +  + array(string) read_attr (string object_name, +  string attr, +  void|string filter, +  void|mapping(string:array(int|string)) controls) + //! Reads a specified attribute of a specified object in the LDAP + //! server. @[object_name] is the distinguished name of the object and + //! @[attr] is the attribute. The rest of the arguments are the same + //! as to @[search]. + //! + //! The default filter that might have been set in the LDAP URL + //! doesn't affect this call. If @[filter] isn't set then + //! @expr{"(objectClass=*)"@} is used. + //! + //! @returns + //! Returns an array containing the values of the attribute on + //! string form. Returns zero if there was an error. + //! + //! @seealso + //! @[read], @[get_root_dse_attr] + { +  if (mapping(string:array(string)) res = +  read (object_name, filter, ({attr}), 0, controls)) { +  m_delete (res, "dn"); +  // Get the value regardless of the case of the attribute name that +  // the server used in the response. +  return get_iterator (res)->value(); +  } +  return 0; + } +    //! Return the LDAP protocol version in use.   int get_protocol_version() {return ldap_version;}       //! @param base_dn    //! base DN for search    string set_basedn (string base_dn) {       string old_dn = ldap_basedn;       if(ldap_version == 3) {    base_dn = string_to_utf8(base_dn);    }    ldap_basedn = base_dn;    DWRITE_HI("client.SET_BASEDN = " + base_dn + "\n");    return old_dn;    }      //! Return the current base DN for searching. - string get_basedn() {return ldap_basedn;} + string get_basedn() {return utf8_to_string (ldap_basedn);}       //!    //! Sets value of scope for search operation.    //!    //! @param scope    //! Value can be integer or its corresponding string value.    //! 0: base, 1: one, 2: sub    //!    int set_scope (int|string scope) {   
pike.git/lib/modules/Protocols.pmod/LDAP.pmod/client.pike:1883:       } //parse_uri         // Schema handling.      static mapping(string:array(string)) query_subschema (string dn,    array(string) attrs)   // Queries the server for the specified attributes in the subschema   // applicable for the specified object. The return value is on the - // same form as from simple_base_query (specifically there's no UTF-8 + // same form as from simple_read (specifically there's no UTF-8   // decoding of the values).   //   // If dn == "" then the attribute values might be joined from several   // schemas. (Might change since I'm not sure whether that's really   // useful or not - haven't got a good grasp on how multiple schemas   // interact in the same server. /mast)   {    mapping(string:array(string)) subschema_response;    int utf8_decode_dns;       if (dn == "" && root_dse)    subschema_response = root_dse;    else {    subschema_response = -  simple_base_query (dn, "(objectClass=*)", ({"subschemaSubentry"})); +  simple_read (dn, "(objectClass=*)", ({"subschemaSubentry"}));    utf8_decode_dns = 1;    }       if (subschema_response)    if (array(string) subschema_dns = subschema_response->subschemasubentry) {    if (sizeof (subschema_dns) == 1) -  return simple_base_query ( +  return simple_read (    utf8_decode_dns ? utf8_to_string (subschema_dns[0]) : subschema_dns[0],    "(objectClass=subschema)", attrs);       else {    // This should afaics only occur for the root DSE, but it's a    // bit confusing: RFC 2252 section 5.1.5 specifies that    // subschemaSubentry is single valued, while RFC 2251 section    // 3.4 says that it can contain zero or more values in the    // root DSE. /mast    mapping(string:array(string)) res = ([]);    foreach (subschema_dns, string subschema_dn) { -  if (mapping(string:array(string)) subres = simple_base_query ( +  if (mapping(string:array(string)) subres = simple_read (    utf8_decode_dns ? utf8_to_string (subschema_dn) : subschema_dn,    "(objectClass=subschema)", attrs))    foreach (indices (subres), string attr)    res[attr] += subres[attr];    }    return res;    }    }       return 0;