📄 squid_ldap_auth.c
字号:
basedn = value; break; case 'f': searchfilter = value; break; case 'u': userattr = value; break; case 'U': passwdattr = value; break; case 's': if (strcmp(value, "base") == 0) searchscope = LDAP_SCOPE_BASE; else if (strcmp(value, "one") == 0) searchscope = LDAP_SCOPE_ONELEVEL; else if (strcmp(value, "sub") == 0) searchscope = LDAP_SCOPE_SUBTREE; else { fprintf(stderr, PROGRAM_NAME ": ERROR: Unknown search scope '%s'\n", value); exit(1); } break; case 'E':#if defined(NETSCAPE_SSL) sslpath = value; if (port == LDAP_PORT) port = LDAPS_PORT;#else fprintf(stderr, PROGRAM_NAME " ERROR: -E unsupported with this LDAP library\n"); exit(1);#endif break; case 'c': connect_timeout = atoi(value); break; case 't': timelimit = atoi(value); break; case 'a': if (strcmp(value, "never") == 0) aliasderef = LDAP_DEREF_NEVER; else if (strcmp(value, "always") == 0) aliasderef = LDAP_DEREF_ALWAYS; else if (strcmp(value, "search") == 0) aliasderef = LDAP_DEREF_SEARCHING; else if (strcmp(value, "find") == 0) aliasderef = LDAP_DEREF_FINDING; else { fprintf(stderr, PROGRAM_NAME ": ERROR: Unknown alias dereference method '%s'\n", value); exit(1); } break; case 'D': binddn = value; break; case 'w': bindpasswd = value; break; case 'W': readSecret(value); break; case 'P': persistent = !persistent; break; case 'O': bind_once = !bind_once; break; case 'p': port = atoi(value); break; case 'R': noreferrals = !noreferrals; break;#ifdef LDAP_VERSION3 case 'v': switch (atoi(value)) { case 2: version = LDAP_VERSION2; break; case 3: version = LDAP_VERSION3; break; default: fprintf(stderr, "Protocol version should be 2 or 3\n"); exit(1); } break; case 'Z': if (version == LDAP_VERSION2) { fprintf(stderr, "TLS (-Z) is incompatible with version %d\n", version); exit(1); } version = LDAP_VERSION3; use_tls = 1; break;#endif case 'd': debug++; break; default: fprintf(stderr, PROGRAM_NAME ": ERROR: Unknown command line option '%c'\n", option); exit(1); } } while (argc > 1) { char *value = argv[1]; if (ldapServer) { int len = strlen(ldapServer) + 1 + strlen(value) + 1; char *newhost = malloc(len); snprintf(newhost, len, "%s %s", ldapServer, value); free(ldapServer); ldapServer = newhost; } else { ldapServer = strdup(value); } argc--; argv++; } if (!ldapServer) ldapServer = strdup("localhost"); if (!basedn) { fprintf(stderr, "Usage: " PROGRAM_NAME " -b basedn [options] [ldap_server_name[:port]]...\n\n"); fprintf(stderr, "\t-b basedn (REQUIRED)\tbase dn under which to search\n"); fprintf(stderr, "\t-f filter\t\tsearch filter to locate user DN\n"); fprintf(stderr, "\t-u userattr\t\tusername DN attribute\n"); fprintf(stderr, "\t-s base|one|sub\t\tsearch scope\n"); fprintf(stderr, "\t-D binddn\t\tDN to bind as to perform searches\n"); fprintf(stderr, "\t-w bindpasswd\t\tpassword for binddn\n"); fprintf(stderr, "\t-W secretfile\t\tread password for binddn from file secretfile\n");#if HAS_URI_SUPPORT fprintf(stderr, "\t-H URI\t\t\tLDAPURI (defaults to ldap://localhost)\n");#endif fprintf(stderr, "\t-h server\t\tLDAP server (defaults to localhost)\n"); fprintf(stderr, "\t-p port\t\t\tLDAP server port\n"); fprintf(stderr, "\t-P\t\t\tpersistent LDAP connection\n");#if defined(NETSCAPE_SSL) fprintf(stderr, "\t-E sslcertpath\t\tenable LDAP over SSL\n");#endif fprintf(stderr, "\t-c timeout\t\tconnect timeout\n"); fprintf(stderr, "\t-t timelimit\t\tsearch time limit\n"); fprintf(stderr, "\t-R\t\t\tdo not follow referrals\n"); fprintf(stderr, "\t-a never|always|search|find\n\t\t\t\twhen to dereference aliases\n");#ifdef LDAP_VERSION3 fprintf(stderr, "\t-v 2|3\t\t\tLDAP version\n"); fprintf(stderr, "\t-Z\t\t\tTLS encrypt the LDAP connection, requires LDAP version 3\n");#endif fprintf(stderr, "\n"); fprintf(stderr, "\tIf no search filter is specified, then the dn <userattr>=user,basedn\n\twill be used (same as specifying a search filter of '<userattr>=',\n\tbut quicker as as there is no need to search for the user DN)\n\n"); fprintf(stderr, "\tIf you need to bind as a user to perform searches then use the\n\t-D binddn -w bindpasswd or -D binddn -W secretfile options\n\n"); exit(1); }/* On windows ldap_start_tls_s is available starting from Windows XP, * so we need to bind at run-time with the function entry point */#ifdef _SQUID_MSWIN_ if (use_tls) { HMODULE WLDAP32Handle; WLDAP32Handle = GetModuleHandle("wldap32"); if ((Win32_ldap_start_tls_s = (PFldap_start_tls_s) GetProcAddress(WLDAP32Handle, LDAP_START_TLS_S)) == NULL) { fprintf(stderr, PROGRAM_NAME ": ERROR: TLS (-Z) not supported on this platform.\n"); exit(1); } }#endif while (fgets(buf, 256, stdin) != NULL) { user = strtok(buf, " \r\n"); passwd = strtok(NULL, "\r\n"); if (!user || !passwd || !passwd[0]) { printf("ERR\n"); continue; } rfc1738_unescape(user); rfc1738_unescape(passwd); if (!validUsername(user)) { printf("ERR No such user\n"); continue; } tryagain = (ld != NULL); recover: if (ld == NULL && persistent) ld = open_ldap_connection(ldapServer, port); if (checkLDAP(ld, user, passwd, ldapServer, port) != 0) { if (tryagain && squid_ldap_errno(ld) != LDAP_INVALID_CREDENTIALS) { tryagain = 0; ldap_unbind(ld); ld = NULL; goto recover; } printf("ERR %s\n", ldap_err2string(squid_ldap_errno(ld))); } else { printf("OK\n"); } if (ld && (squid_ldap_errno(ld) != LDAP_SUCCESS && squid_ldap_errno(ld) != LDAP_INVALID_CREDENTIALS)) { ldap_unbind(ld); ld = NULL; } } if (ld) ldap_unbind(ld); return 0;}static intldap_escape_value(char *escaped, int size, const char *src){ int n = 0; while (size > 4 && *src) { switch (*src) { case '*': case '(': case ')': case '\\': n += 3; size -= 3; if (size > 0) { *escaped++ = '\\'; snprintf(escaped, 3, "%02x", (unsigned char) *src++); escaped += 2; } break; default: *escaped++ = *src++; n++; size--; } } *escaped = '\0'; return n;}/* Check the userid & password. * Return 0 on success, 1 on failure */static intcheckLDAP(LDAP * persistent_ld, const char *userid, const char *password, const char *ldapServer, int port){ char dn[256]; int ret = 0; LDAP *bind_ld = NULL; int rc; if (!*password) { /* LDAP can't bind with a blank password. Seen as "anonymous" * and always granted access */ if (debug) fprintf(stderr, "Blank password given\n"); return 1; } if (searchfilter) { char filter[256]; char escaped_login[256]; LDAPMessage *res = NULL; LDAPMessage *entry; char *searchattr[] = {LDAP_NO_ATTRS, NULL}; char *userdn; LDAP *search_ld = persistent_ld; if (!search_ld) search_ld = open_ldap_connection(ldapServer, port); ldap_escape_value(escaped_login, sizeof(escaped_login), userid); if (binddn) { rc = ldap_simple_bind_s(search_ld, binddn, bindpasswd); if (rc != LDAP_SUCCESS) { fprintf(stderr, PROGRAM_NAME ": WARNING, could not bind to binddn '%s'\n", ldap_err2string(rc)); ret = 1; goto search_done; } } snprintf(filter, sizeof(filter), searchfilter, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login); if (debug) fprintf(stderr, "user filter '%s', searchbase '%s'\n", filter, basedn); rc = ldap_search_s(search_ld, basedn, searchscope, filter, searchattr, 1, &res); if (rc != LDAP_SUCCESS) { if (noreferrals && rc == LDAP_PARTIAL_RESULTS) { /* Everything is fine. This is expected when referrals * are disabled. */ if (debug) fprintf(stderr, "noreferrals && rc == LDAP_PARTIAL_RESULTS\n"); } else { fprintf(stderr, PROGRAM_NAME ": WARNING, LDAP search error '%s'\n", ldap_err2string(rc));#if defined(NETSCAPE_SSL) if (sslpath && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR))) { int sslerr = PORT_GetError(); fprintf(stderr, PROGRAM_NAME ": WARNING, SSL error %d (%s)\n", sslerr, ldapssl_err2string(sslerr)); }#endif ret = 1; goto search_done; } } entry = ldap_first_entry(search_ld, res); if (!entry) { if (debug) fprintf(stderr, "Ldap search returned nothing\n"); ret = 1; goto search_done; } userdn = ldap_get_dn(search_ld, entry); if (!userdn) { fprintf(stderr, PROGRAM_NAME ": ERROR, could not get user DN for '%s'\n", userid); ret = 1; goto search_done; } snprintf(dn, sizeof(dn), "%s", userdn); squid_ldap_memfree(userdn); if (ret == 0 && (!binddn || !bind_once || passwdattr)) { /* Reuse the search connection for comparing the user password attribute */ bind_ld = search_ld; search_ld = NULL; } search_done: if (res) { ldap_msgfree(res); res = NULL; } if (search_ld && search_ld != persistent_ld) { ldap_unbind(search_ld); search_ld = NULL; } if (ret != 0) return ret; } else { snprintf(dn, sizeof(dn), "%s=%s,%s", userattr, userid, basedn); } if (debug) fprintf(stderr, "attempting to authenticate user '%s'\n", dn); if (!bind_ld && !bind_once) bind_ld = persistent_ld; if (!bind_ld) bind_ld = open_ldap_connection(ldapServer, port); if (passwdattr) { if (ldap_compare_s(bind_ld, dn, passwdattr, password) != LDAP_COMPARE_TRUE) { ret = 1; } } else if (ldap_simple_bind_s(bind_ld, dn, password) != LDAP_SUCCESS) ret = 1; if (bind_ld != persistent_ld) { ldap_unbind(bind_ld); bind_ld = NULL; } return ret;}intreadSecret(const char *filename){ char buf[BUFSIZ]; char *e = NULL; FILE *f; char *passwd = NULL; if (!(f = fopen(filename, "r"))) { fprintf(stderr, PROGRAM_NAME " ERROR: Can not read secret file %s\n", filename); return 1; } if (!fgets(buf, sizeof(buf) - 1, f)) { fprintf(stderr, PROGRAM_NAME " ERROR: Secret file %s is empty\n", filename); fclose(f); return 1; } /* strip whitespaces on end */ if ((e = strrchr(buf, '\n'))) *e = 0; if ((e = strrchr(buf, '\r'))) *e = 0; passwd = (char *) calloc(sizeof(char), strlen(buf) + 1); if (!passwd) { fprintf(stderr, PROGRAM_NAME " ERROR: can not allocate memory\n"); exit(1); } strcpy(passwd, buf); bindpasswd = passwd; fclose(f); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -