Thread: C, custom function, return values and loops

  1. #1
    Registered User
    Join Date
    Jul 2009
    Posts
    4

    C, custom function, return values and loops

    This might be a bit to ask but I am stumped. I am not a very experienced C programmer but have written some code in the past.

    Currently I am adding some functionality to an existing authentication module for linux utilizing the openldap api and have hit a wall.

    I am going to post the function in its entirety as well as how the function is being called...

    This function I use to perform a simple check on struct values which were obtained from a configuration file. This works fine and returns a 1 on error or a 0 on success.
    Code:
    int
    _check_ldap_options(struct _pam_krb5_options *options)
    {
      if( ( strlen(options->schema) < 0 ) || ( strlen(options->schema) > 5 ) ) { return(1); }
      if( ( strlen(options->ldapservs) < 0 ) || ( strlen(options->ldapservs) > 255 ) ) { return(1); }
      if( ( strlen(options->ldapport) < 0 ) || ( strlen(options->ldapport) > 4 ) ) { return(1); }
      if( ( strlen(options->binddn) < 0 ) || ( strlen(options->binddn) > 255 ) ) { return(1); }
      if( ( strlen(options->basedn) < 0 ) || (strlen(options->basedn) > 255 ) ) { return(1); }
      if( ( strlen(options->ldapuser) < 0 ) || ( strlen(options->ldapuser) > 40 ) ) { return(1); }
      if( ( strlen(options->ldappass) < 0 ) || (strlen(options->ldappass) > 40 ) ) { return(1); }
      return(0);
    }
    This function is used to perform the init, bind, search and get values regarding the ldap api. This also works fine as each value I am looking for in active directory and ldap is returned and stored within the existing struct; struct _pam_krb5_user_info *userinfo.
    Code:
    int
    _ldap_search(struct _pam_krb5_options *options, char *user, struct _pam_krb5_user_info *userinfo)
    {
      LDAP *ld;
      LDAPMessage *res, *e;
      BerElement *ptr;
    
      int i, rc, port;
      char *host, *base;
      const char *luser, *pass;
      char buffer[80], **vals;
      const char *attrs;
    
      if (options->schema == "ad") {
        attrs = "homeDirectory";
      } else {
        attrs = "msSFUHomeDirectory";
      }
    
      host = options->ldapservs;
      port = LDAP_PORT;
      //port = options->ldapport;
      luser = options->ldapuser;
      pass = options->ldappass;
      base = options->basedn;
    
    
      if ((ld = ldap_init(host, port)) == NULL) {
        crit("error connecting to %s", options->ldapservs);
        return(1);
      } else {
        if (ldap_simple_bind_s(ld, luser, pass) == LDAP_SUCCESS) {
    
          snprintf(buffer, sizeof(buffer), "(cn=%s)", user);
          warn("searching '%s' for '%s'...", options->basedn, user);
    
          if (ldap_search_s(ld, options->basedn, LDAP_SCOPE_SUBTREE, buffer, NULL, 0, &res) != LDAP_SUCCESS) {
            crit( "error occured while searching for %s", buffer);
            return(1);
          }
    
          if(ldap_first_entry(ld, res) == NULL) {
            crit("'%s' not found in '%s' aborting authentication", user, options->basedn);
            return(1);
          }
    
          for (e = ldap_first_entry(ld, res); e != NULL; e = ldap_next_entry(ld, e)) {
    
            vals = ldap_get_values(ld, e, "uidNumber");
            for (i = 0; vals[i] != NULL; i++) {
              userinfo->uid = atoi(vals[i]);
              debug("uid: %d", userinfo->uid);
            }
    
    
            vals = ldap_get_values(ld, e, "gidNumber");
            for (i = 0; vals[i] != NULL; i++) {
              userinfo->gid = atoi(vals[i]);
              debug("gid: %d", userinfo->gid);
            }
    
            vals = ldap_get_values(ld, e, attrs);
            for (i = 0; vals[i] != NULL; i++) {
              snprintf(buffer, sizeof(buffer), "%s%s", vals[i], user);
              userinfo->homedir = buffer;
              debug("homedir: %s", userinfo->homedir);
            }
    
            vals = ldap_get_values(ld, e, "loginShell");
            for (i = 0; vals[i] != NULL; i++) {
              userinfo->shell = vals[i];
              debug("loginshell: %s", userinfo->shell);
            }
            ldap_value_free(vals);
    
          }
          ldap_msgfree(res);
          ldap_unbind(ld);
    
          return(0);
    
        } else {
          crit("%s", ldap_err2string(ldap_simple_bind_s(ld, luser, pass)));
          return(1);
        }
      }
    }
    This next portion is where I am running into a wall. It seems that the entire application halts when _ldap_search() is called. During testing the return value it will perform as expected

    Code:
            if (_check_ldap_options(options) != 0 ) {
              warn("missing configuration options. aborting ad/ldap lookup, checking locally...");
            } else {
              if (_ldap_search(options, &local_name, &ret) != 0 ) {
                warn("error looking up user in ad/ldap, checking locally...");
              } else {
                warn("%s => %s => %s", ret->uid, ret->gid, ret->homedir);
                ret->uid = -1;
                ret->gid = -1;
                ret->homedir = xstrdup("/");
              }
            }
    The second else statement is where it fails to put anything in the logs. If I perform a function call such as the following I get the desired return value and it continues without problem.

    Code:
    warn("results: %d", _ldap_search(options, &local_name, &ret));
    Some more background... the 'options' argument is a struct of configuration options needed to connect and search active directory/ldap. the 'local_name' is the username i am searching for and '&ret' is the struct i am attempting to modify.

    I do believe the problem lies in how I am attempting to modify the existing &ret struct variables. Any help is appreciated.

  2. #2
    Registered User slingerland3g's Avatar
    Join Date
    Jan 2008
    Location
    Seattle
    Posts
    603
    At first glance your warn function is requiring three strings as arguments, is that really the case, though your compiler would error out otherwise. How is your struct for ret being initialized or populated?

  3. #3
    Registered User
    Join Date
    Jul 2009
    Posts
    4
    Quote Originally Posted by slingerland3g View Post
    At first glance your warn function is requiring three strings as arguments, is that really the case, though your compiler would error out otherwise. How is your struct for ret being initialized or populated?
    Actually the warn only accepts one argument which is the return value of the _search_ldap() function. In this case a 1 on error or 0.

  4. #4
    Registered User slingerland3g's Avatar
    Join Date
    Jan 2008
    Location
    Seattle
    Posts
    603
    Sorry, I was refering to this statement:

    [/code]
    warn("%s => %s => %s", ret->uid, ret->gid, ret->homedir);
    [code]

    So where at in your code snipit is this other second else statement with this warn()? Is this warn() some form of a variadic macro function?

  5. #5
    Registered User
    Join Date
    Jul 2009
    Posts
    4
    Yeah that is a function defined as so...

    Code:
    void
    warn(const char *fmt, ...)
    {
            va_list args;
            char *fmt2;
    
            va_start(args, fmt);
    
            fmt2 = malloc(strlen(PACKAGE) + 4 + llen(getpid()) + strlen(fmt) + 1);
            if (fmt2 != NULL) {
                    sprintf(fmt2, "%s[%lu]: %s", PACKAGE,
                            (unsigned long) getpid(), fmt);
                    vsyslog(PACKAGE_FACILITY | LOG_WARNING, fmt2, args);
                    free(fmt2);
            } else {
                    vsyslog(PACKAGE_FACILITY | LOG_WARNING, fmt, args);
            }
    
            va_end(args);
    }

  6. #6
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    I'm a bit more curious about about the returns of _ldap_search function. Is it returning 0? Is the ret pointing to valid struct memory. Can you use some print statment to print the ret struct values and check if it can print any values?

    And check where the control is jumping to? Check if the _ldap_search return a non-zero value?

    ~ssharish
    Life is like riding a bicycle. To keep your balance you must keep moving - Einstein

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. My most amazing error yet! [complicated]
    By therabidwombat in forum C++ Programming
    Replies: 33
    Last Post: 11-02-2006, 02:54 PM
  2. Replies: 16
    Last Post: 10-29-2006, 05:04 AM
  3. Replies: 11
    Last Post: 03-24-2006, 11:26 AM
  4. return, cout and two values
    By s_UNI_ in forum C++ Programming
    Replies: 2
    Last Post: 05-15-2005, 08:47 PM
  5. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM