在C中处理ldap_初始化时出错

在C中处理ldap_初始化时出错,c,error-handling,ldap,pam,C,Error Handling,Ldap,Pam,背景 我在处理C中的ldap_initialize函数时遇到问题 在阅读了大量文档(大多数只是手册页的平版副本)后,我发现了一些可能误导或错误处理此功能的方法 以下是我遇到问题的代码: //-------------------------------------- // declarations //-------------------------------------- int status = 0; int optionHandlingStatus = 0; char * ldapEr

背景 我在处理C中的ldap_initialize函数时遇到问题

在阅读了大量文档(大多数只是手册页的平版副本)后,我发现了一些可能误导或错误处理此功能的方法

以下是我遇到问题的代码:

//--------------------------------------
// declarations
//--------------------------------------
int status = 0;
int optionHandlingStatus = 0;
char * ldapErrorString = NULL;
char serverAddress[PLS_STRING_ARRAY_SIZE];

//--------------------------------------
// prepare the server's address
//--------------------------------------
sprintf(
    serverAddress,
    "ldap://%s:%s",
    settings->serverAddress,
    settings->serverPort
);
//writeDebugLog("LDAP server address set to [%s].", serverAddress);

//--------------------------------------
// connect to the server
//--------------------------------------
status = ldap_initialize(&ldapServerConnection, serverAddress);
optionHandlingStatus = ldap_get_option(ldapServerConnection, LDAP_OPT_RESULT_CODE, &status);
if (status != LDAP_SUCCESS || errno != LDAP_SUCCESS) { //the specs are strange
    if (status && errno) {
        writeDebugLog("CONNECTION Fail!.");
        writeSyslog("CONNECTION Fail!.");
    }
    ldapErrorString = ldap_err2string(status);
    writeDebugLog("Connection to server failed with [%s].", ldapErrorString);
    writeSyslog(
        "LDAP server initalization error. Check [%s] server's status.",
        serverAddress
    );
    return(NULL);
}  
问题 文件指出,ldap_初始化应该: 1.如果使用ldap_init,则在出现连接错误时返回空指针 2.返回可以使用ldap\u get\u选项获取的错误状态

然而,这两种方法都不可靠。我已经对我创建的用于启动LDAP服务器连接的函数进行了彻底的测试。有时,ldap_init返回指向ldap对象的有效指针,ldap_initialize返回错误代码ldap success(在使用ldap_get_选项时),ldap_get_选项在解析错误代码时成功返回

我发现,如果我检查C的errno变量,我可以相当准确地获得ldap_initialize函数的连接状态,因为当它失败时,它似乎正在设置errno errno==2=>没有这样的文件或目录

当我在程序中指定随机未使用的端口时,这通常是准确的。然而,我用一个名为pamtester的程序更彻底地测试了我的程序,它无法验证我指定的用户。在我调用ldap\u initialize之后,设置的错误是没有这样的文件或目录

在ldap_初始化之后,我强制设置了C的errno=0,并且我能够成功地根据我的ldap数据库对用户进行身份验证

问题 1.处理ldap_initialize函数错误的正确方法是什么? 2.我应该使用不同的函数来初始化LDAP连接吗? 3.如果错误状态实际上是由C的errno标志处理的,而不是由ldap_get_选项处理的,那么为什么所有的手册页和示例都不是这样

仅在ldap\u initilize返回与ldap\u SUCCESS不同的结果时检查errno。在ldap_initilize返回后立即执行此操作,否则其他Weise errno可能会被破坏

代码应如下所示:

int status = ldap_initialize(&ldapServerConnection, serverAddress);
if (status != LDAP_SUCCESS)
{
  /* int errno_save = errno; */
  perror("ldap_initialize() failed"); /* This call shows the error message related to errno. */
  /* If on a GNU system also the following will do: */
  /* fprintf(stderr, ""ldap_initialize() failed with #%d: '%s'\n", errno_save, strerror(errno_save)); */

  writeDebugLog("CONNECTION Fail!.");
  writeSyslog("CONNECTION Fail!.");

  ldapErrorString = ldap_err2string(status);
  writeDebugLog("Connection to server failed with [%s].", ldapErrorString);
  writeSyslog(
    "LDAP server initalization error. Check [%s] server's status.",
    serverAddress
  );
  return(NULL);
}
更新:

使用ldap_init*函数不会尝试建立连接,因此不会检测到任何无效的地址数据。要实际测试连接,请使用ldap_open,而不是ldsp_init

发件人:

ldap_init的作用与ldap_open类似,但不打开到ldap服务器的连接。尝试第一次操作时,将出现实际连接打开


仅当ldap_initilize返回了一些不同的错误,然后ldap_成功时才检查errno。在ldap_initilize返回后立即执行此操作,否则其他Weise errno可能会被破坏。在返回``ldap\u initilize`后,另一种方法是保存errno的值。我不知道您一直在阅读哪些手册页,但错误部分似乎相当清楚:我一直在这样做,但是,问题是有时ldap\u initialize会在无效连接上返回ldap\u SUCCESS,但会设置errno。错误处理一直存在冲突,让我感到困惑,因此我在这里发布。您不会这样做,至少在您展示给我们的代码中不会。除非函数返回一个指示失败的值,否则errno是没有意义的。如果库函数成功,则不会将errno设置为0。在调用函数之前,请尝试将errno设置为0,如果函数成功返回,则errno应仍然为0。我将尝试您的建议,看看会发生什么。请稍等。我试过你的建议,我似乎也遇到了同样的麻烦。status==LDAP_SUCCESS,即使我故意将服务器地址设置为不存在的地址。ldap://123.45.67.89:9321You 需要调用ldap_open以发现此地址无效。我现在就给它打电话。我应该把ldap_initalize称为ldap_open,然后像这样依次打开ldap_open?看起来答案就是ldap_open。我还要再检查几次。