3363 lines
265 KiB
HTML
3363 lines
265 KiB
HTML
|
<!DOCTYPE html><html lang="fr">
|
|||
|
<head><meta charset="utf-8">
|
|||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|||
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>OpenLDAP installation et configuration annuaire - YannStatic</title>
|
|||
|
|
|||
|
<meta name="description" content="OpenLDAP Debian">
|
|||
|
<link rel="canonical" href="https://static.rnmkcy.eu/2019/10/05/OpenLDAP-installation-configuration-annuaire.html"><link rel="alternate" type="application/rss+xml" title="YannStatic" href="/feed.xml">
|
|||
|
|
|||
|
<!-- - include head/favicon.html - -->
|
|||
|
<link rel="shortcut icon" type="image/png" href="/assets/favicon/favicon.png"><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets --><link rel="stylesheet" href="/assets/css/expand.css">
|
|||
|
<!-- end custom head snippets --><script>(function() {
|
|||
|
window.isArray = function(val) {
|
|||
|
return Object.prototype.toString.call(val) === '[object Array]';
|
|||
|
};
|
|||
|
window.isString = function(val) {
|
|||
|
return typeof val === 'string';
|
|||
|
};
|
|||
|
|
|||
|
window.hasEvent = function(event) {
|
|||
|
return 'on'.concat(event) in window.document;
|
|||
|
};
|
|||
|
|
|||
|
window.isOverallScroller = function(node) {
|
|||
|
return node === document.documentElement || node === document.body || node === window;
|
|||
|
};
|
|||
|
|
|||
|
window.isFormElement = function(node) {
|
|||
|
var tagName = node.tagName;
|
|||
|
return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
|
|||
|
};
|
|||
|
|
|||
|
window.pageLoad = (function () {
|
|||
|
var loaded = false, cbs = [];
|
|||
|
window.addEventListener('load', function () {
|
|||
|
var i;
|
|||
|
loaded = true;
|
|||
|
if (cbs.length > 0) {
|
|||
|
for (i = 0; i < cbs.length; i++) {
|
|||
|
cbs[i]();
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
return {
|
|||
|
then: function(cb) {
|
|||
|
cb && (loaded ? cb() : (cbs.push(cb)));
|
|||
|
}
|
|||
|
};
|
|||
|
})();
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
window.throttle = function(func, wait) {
|
|||
|
var args, result, thisArg, timeoutId, lastCalled = 0;
|
|||
|
|
|||
|
function trailingCall() {
|
|||
|
lastCalled = new Date;
|
|||
|
timeoutId = null;
|
|||
|
result = func.apply(thisArg, args);
|
|||
|
}
|
|||
|
return function() {
|
|||
|
var now = new Date,
|
|||
|
remaining = wait - (now - lastCalled);
|
|||
|
|
|||
|
args = arguments;
|
|||
|
thisArg = this;
|
|||
|
|
|||
|
if (remaining <= 0) {
|
|||
|
clearTimeout(timeoutId);
|
|||
|
timeoutId = null;
|
|||
|
lastCalled = now;
|
|||
|
result = func.apply(thisArg, args);
|
|||
|
} else if (!timeoutId) {
|
|||
|
timeoutId = setTimeout(trailingCall, remaining);
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
};
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var Set = (function() {
|
|||
|
var add = function(item) {
|
|||
|
var i, data = this._data;
|
|||
|
for (i = 0; i < data.length; i++) {
|
|||
|
if (data[i] === item) {
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
this.size ++;
|
|||
|
data.push(item);
|
|||
|
return data;
|
|||
|
};
|
|||
|
|
|||
|
var Set = function(data) {
|
|||
|
this.size = 0;
|
|||
|
this._data = [];
|
|||
|
var i;
|
|||
|
if (data.length > 0) {
|
|||
|
for (i = 0; i < data.length; i++) {
|
|||
|
add.call(this, data[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
Set.prototype.add = add;
|
|||
|
Set.prototype.get = function(index) { return this._data[index]; };
|
|||
|
Set.prototype.has = function(item) {
|
|||
|
var i, data = this._data;
|
|||
|
for (i = 0; i < data.length; i++) {
|
|||
|
if (this.get(i) === item) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
};
|
|||
|
Set.prototype.is = function(map) {
|
|||
|
if (map._data.length !== this._data.length) { return false; }
|
|||
|
var i, j, flag, tData = this._data, mData = map._data;
|
|||
|
for (i = 0; i < tData.length; i++) {
|
|||
|
for (flag = false, j = 0; j < mData.length; j++) {
|
|||
|
if (tData[i] === mData[j]) {
|
|||
|
flag = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (!flag) { return false; }
|
|||
|
}
|
|||
|
return true;
|
|||
|
};
|
|||
|
Set.prototype.values = function() {
|
|||
|
return this._data;
|
|||
|
};
|
|||
|
return Set;
|
|||
|
})();
|
|||
|
|
|||
|
window.Lazyload = (function(doc) {
|
|||
|
var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
|
|||
|
var createNode = function(name, attrs) {
|
|||
|
var node = doc.createElement(name), attr;
|
|||
|
for (attr in attrs) {
|
|||
|
if (attrs.hasOwnProperty(attr)) {
|
|||
|
node.setAttribute(attr, attrs[attr]);
|
|||
|
}
|
|||
|
}
|
|||
|
return node;
|
|||
|
};
|
|||
|
var end = function(type, url) {
|
|||
|
var s, q, qi, cbs, i, j, cur, val, flag;
|
|||
|
if (type === 'js' || type ==='css') {
|
|||
|
s = sources[type], q = queue[type];
|
|||
|
s[url] = true;
|
|||
|
for (i = 0; i < q.length; i++) {
|
|||
|
cur = q[i];
|
|||
|
if (cur.urls.has(url)) {
|
|||
|
qi = cur, val = qi.urls.values();
|
|||
|
qi && (cbs = qi.callbacks);
|
|||
|
for (flag = true, j = 0; j < val.length; j++) {
|
|||
|
cur = val[j];
|
|||
|
if (!s[cur]) {
|
|||
|
flag = false;
|
|||
|
}
|
|||
|
}
|
|||
|
if (flag && cbs && cbs.length > 0) {
|
|||
|
for (j = 0; j < cbs.length; j++) {
|
|||
|
cbs[j].call(context);
|
|||
|
}
|
|||
|
qi.load = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
var load = function(type, urls, callback) {
|
|||
|
var s, q, qi, node, i, cur,
|
|||
|
_urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
|
|||
|
if (type === 'js' || type ==='css') {
|
|||
|
s = sources[type], q = queue[type];
|
|||
|
for (i = 0; i < q.length; i++) {
|
|||
|
cur = q[i];
|
|||
|
if (_urls.is(cur.urls)) {
|
|||
|
qi = cur;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
val = _urls.values();
|
|||
|
if (qi) {
|
|||
|
callback && (qi.load || qi.callbacks.push(callback));
|
|||
|
callback && (qi.load && callback());
|
|||
|
} else {
|
|||
|
q.push({
|
|||
|
urls: _urls,
|
|||
|
callbacks: callback ? [callback] : [],
|
|||
|
load: false
|
|||
|
});
|
|||
|
for (i = 0; i < val.length; i++) {
|
|||
|
node = null, url = val[i];
|
|||
|
if (s[url] === undefined) {
|
|||
|
(type === 'js' ) && (node = createNode('script', { src: url }));
|
|||
|
(type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
|
|||
|
if (node) {
|
|||
|
node.onload = (function(type, url) {
|
|||
|
return function() {
|
|||
|
end(type, url);
|
|||
|
};
|
|||
|
})(type, url);
|
|||
|
(doc.head || doc.body).appendChild(node);
|
|||
|
s[url] = false;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
return {
|
|||
|
js: function(url, callback) {
|
|||
|
load('js', url, callback);
|
|||
|
},
|
|||
|
css: function(url, callback) {
|
|||
|
load('css', url, callback);
|
|||
|
}
|
|||
|
};
|
|||
|
})(this.document);
|
|||
|
})();
|
|||
|
</script><script>
|
|||
|
(function() {
|
|||
|
var TEXT_VARIABLES = {
|
|||
|
version: '2.2.6',
|
|||
|
sources: {
|
|||
|
font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
|
|||
|
jquery: '/assets/js/jquery.min.js',
|
|||
|
leancloud_js_sdk: '//cdn.jsdelivr.net/npm/leancloud-storage@3.13.2/dist/av-min.js',
|
|||
|
chart: 'https://cdn.bootcss.com/Chart.js/2.7.2/Chart.bundle.min.js',
|
|||
|
gitalk: {
|
|||
|
js: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.js',
|
|||
|
css: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.css'
|
|||
|
},
|
|||
|
valine: 'https://unpkg.com/valine/dist/Valine.min.js'
|
|||
|
},
|
|||
|
site: {
|
|||
|
toc: {
|
|||
|
selectors: 'h1,h2,h3'
|
|||
|
}
|
|||
|
},
|
|||
|
paths: {
|
|||
|
search_js: '/assets/search.js'
|
|||
|
}
|
|||
|
};
|
|||
|
window.TEXT_VARIABLES = TEXT_VARIABLES;
|
|||
|
})();
|
|||
|
</script>
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
<div class="root" data-is-touch="false">
|
|||
|
<div class="layout--page js-page-root"><!----><div class="page__main js-page-main page__viewport hide-footer has-aside has-aside cell cell--auto">
|
|||
|
|
|||
|
<div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
|
|||
|
<div class="header__title">
|
|||
|
<div class="header__brand"><svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="478.9473684210526" viewBox="0, 0, 400,478.9473684210526"><g id="svgg"><path id="path0" d="M308.400 56.805 C 306.970 56.966,303.280 57.385,300.200 57.738 C 290.906 58.803,278.299 59.676,269.200 59.887 L 260.600 60.085 259.400 61.171 C 258.010 62.428,256.198 63.600,255.645 63.600 C 255.070 63.600,252.887 65.897,252.598 66.806 C 252.460 67.243,252.206 67.600,252.034 67.600 C 251.397 67.600,247.206 71.509,247.202 72.107 C 247.201 72.275,246.390 73.190,245.400 74.138 C 243.961 75.517,243.598 76.137,243.592 77.231 C 243.579 79.293,241.785 83.966,240.470 85.364 C 239.176 86.740,238.522 88.365,237.991 91.521 C 237.631 93.665,236.114 97.200,235.554 97.200 C 234.938 97.200,232.737 102.354,232.450 104.472 C 232.158 106.625,230.879 109.226,229.535 110.400 C 228.933 110.926,228.171 113.162,226.434 119.500 C 226.178 120.435,225.795 121.200,225.584 121.200 C 225.373 121.200,225.200 121.476,225.200 121.813 C 225.200 122.149,224.885 122.541,224.500 122.683 C 223.606 123.013,223.214 123.593,223.204 124.600 C 223.183 126.555,220.763 132.911,219.410 134.562 C 218.443 135.742,217.876 136.956,217.599 138.440 C 217.041 141.424,215.177 146.434,214.532 146.681 C 214.240 146.794,214.000 147.055,214.000 147.261 C 214.000 147.467,213.550 148.086,213.000 148.636 C 212.450 149.186,212.000 149.893,212.000 150.208 C 212.000 151.386,208.441 154.450,207.597 153.998 C 206.319 153.315,204.913 150.379,204.633 147.811 C 204.365 145.357,202.848 142.147,201.759 141.729 C 200.967 141.425,199.200 137.451,199.200 135.974 C 199.200 134.629,198.435 133.224,196.660 131.311 C 195.363 129.913,194.572 128.123,193.870 125.000 C 193.623 123.900,193.236 122.793,193.010 122.540 C 190.863 120.133,190.147 118.880,188.978 115.481 C 188.100 112.928,187.151 111.003,186.254 109.955 C 185.358 108.908,184.518 107.204,183.847 105.073 C 183.280 103.273,182.497 101.329,182.108 100.753 C 181.719 100.177,180.904 98.997,180.298 98.131 C 179.693 97.265,178.939 95.576,178.624 94.378 C 178.041 92.159,177.125 90.326,175.023 87.168 C 174.375 86.196,173.619 84.539,173.342 83.486 C 172.800 81.429,171.529 79.567,170.131 78.785 C 169.654 78.517,168.697 77.511,168.006 76.549 C 167.316 75.587,166.594 74.800,166.402 74.800 C 166.210 74.800,164.869 73.633,163.421 72.206 C 160.103 68.936,161.107 69.109,146.550 69.301 C 133.437 69.474,128.581 70.162,126.618 72.124 C 126.248 72.495,125.462 72.904,124.872 73.033 C 124.282 73.163,123.088 73.536,122.219 73.863 C 121.349 74.191,119.028 74.638,117.061 74.858 C 113.514 75.254,109.970 76.350,108.782 77.419 C 107.652 78.436,100.146 80.400,97.388 80.400 C 95.775 80.400,93.167 81.360,91.200 82.679 C 90.430 83.195,89.113 83.804,88.274 84.031 C 85.875 84.681,78.799 90.910,74.400 96.243 L 73.400 97.456 73.455 106.028 C 73.526 117.055,74.527 121.238,77.820 124.263 C 78.919 125.273,80.400 127.902,80.400 128.842 C 80.400 129.202,81.075 130.256,81.900 131.186 C 83.563 133.059,85.497 136.346,86.039 138.216 C 86.233 138.886,87.203 140.207,88.196 141.153 C 89.188 142.098,90.000 143.104,90.000 143.388 C 90.000 144.337,92.129 148.594,92.869 149.123 C 93.271 149.410,93.600 149.831,93.600 150.059 C 93.600 150.286,93.932 150.771,94.337 151.136 C 94.743 151.501,95.598 153.004,96.237 154.475 C 96.877 155.947,97.760 157.351,98.200 157.596 C 98.640 157.841,99.900 159.943,101.000 162.267 C 102.207 164.817,103.327 166.644,103.825 166.876 C 104.278 167.087,105.065 168.101,105.573 169.130 C 107.658 173.348,108.097 174.093,110.006 176.647 C 111.103 178.114,112.000 179.725,112.000 180.227 C 112.000 181.048,113.425 183.163,114.678 184.200 C 115.295 184.711,117.396 188.733,117.720 190.022 C 117.855 190.562,118.603 191.633,119.381 192.402 C 120.160 193.171,121.496 195.258,122.351 197.039 C 123.206 198.820,124.167 200.378,124.487 200.501 C 124.807 200.624,125.953 202.496,127.034 204.662 C 128.114 206.828,129.676 209.299,130.505 210.153 C 131.333 211.007,132.124 212.177,132.262 212.753 C 132.618 214.239,134.291 217.048,136.288 219.5
|
|||
|
" href="/">YannStatic</a></div><!--<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>--><!-- <li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li> -->
|
|||
|
<!-- Champ de recherche -->
|
|||
|
<div id="searchbox" class="search search--dark" style="visibility: visible">
|
|||
|
<div class="main">
|
|||
|
<div class="search__header"></div>
|
|||
|
<div class="search-bar">
|
|||
|
<div class="search-box js-search-box">
|
|||
|
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
|
|||
|
<input id="search-input" type="text" />
|
|||
|
<!-- <div class="search-box__icon-clear js-icon-clear">
|
|||
|
<a><i class="fas fa-times"></i></a>
|
|||
|
</div> -->
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<!-- Script pointing to search-script.js -->
|
|||
|
<script>/*!
|
|||
|
* Simple-Jekyll-Search
|
|||
|
* Copyright 2015-2020, Christian Fei
|
|||
|
* Licensed under the MIT License.
|
|||
|
*/
|
|||
|
|
|||
|
(function(){
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Templater_7 = {
|
|||
|
compile: compile,
|
|||
|
setOptions: setOptions
|
|||
|
}
|
|||
|
|
|||
|
const options = {}
|
|||
|
options.pattern = /\{(.*?)\}/g
|
|||
|
options.template = ''
|
|||
|
options.middleware = function () {}
|
|||
|
|
|||
|
function setOptions (_options) {
|
|||
|
options.pattern = _options.pattern || options.pattern
|
|||
|
options.template = _options.template || options.template
|
|||
|
if (typeof _options.middleware === 'function') {
|
|||
|
options.middleware = _options.middleware
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function compile (data) {
|
|||
|
return options.template.replace(options.pattern, function (match, prop) {
|
|||
|
const value = options.middleware(prop, data[prop], options.template)
|
|||
|
if (typeof value !== 'undefined') {
|
|||
|
return value
|
|||
|
}
|
|||
|
return data[prop] || match
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
'use strict';
|
|||
|
|
|||
|
function fuzzysearch (needle, haystack) {
|
|||
|
var tlen = haystack.length;
|
|||
|
var qlen = needle.length;
|
|||
|
if (qlen > tlen) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
if (qlen === tlen) {
|
|||
|
return needle === haystack;
|
|||
|
}
|
|||
|
outer: for (var i = 0, j = 0; i < qlen; i++) {
|
|||
|
var nch = needle.charCodeAt(i);
|
|||
|
while (j < tlen) {
|
|||
|
if (haystack.charCodeAt(j++) === nch) {
|
|||
|
continue outer;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
var _$fuzzysearch_1 = fuzzysearch;
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
|
|||
|
|
|||
|
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
|
|||
|
|
|||
|
function FuzzySearchStrategy () {
|
|||
|
this.matches = function (string, crit) {
|
|||
|
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
|
|||
|
|
|||
|
function LiteralSearchStrategy () {
|
|||
|
this.matches = function (str, crit) {
|
|||
|
if (!str) return false
|
|||
|
|
|||
|
str = str.trim().toLowerCase()
|
|||
|
crit = crit.trim().toLowerCase()
|
|||
|
|
|||
|
return crit.split(' ').filter(function (word) {
|
|||
|
return str.indexOf(word) >= 0
|
|||
|
}).length === crit.split(' ').length
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Repository_4 = {
|
|||
|
put: put,
|
|||
|
clear: clear,
|
|||
|
search: search,
|
|||
|
setOptions: __setOptions_4
|
|||
|
}
|
|||
|
|
|||
|
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
|
|||
|
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
|
|||
|
|
|||
|
function NoSort () {
|
|||
|
return 0
|
|||
|
}
|
|||
|
|
|||
|
const data = []
|
|||
|
let opt = {}
|
|||
|
|
|||
|
opt.fuzzy = false
|
|||
|
opt.limit = 10
|
|||
|
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = NoSort
|
|||
|
opt.exclude = []
|
|||
|
|
|||
|
function put (data) {
|
|||
|
if (isObject(data)) {
|
|||
|
return addObject(data)
|
|||
|
}
|
|||
|
if (isArray(data)) {
|
|||
|
return addArray(data)
|
|||
|
}
|
|||
|
return undefined
|
|||
|
}
|
|||
|
function clear () {
|
|||
|
data.length = 0
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function isObject (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
|
|||
|
}
|
|||
|
|
|||
|
function isArray (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
|
|||
|
}
|
|||
|
|
|||
|
function addObject (_data) {
|
|||
|
data.push(_data)
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function addArray (_data) {
|
|||
|
const added = []
|
|||
|
clear()
|
|||
|
for (let i = 0, len = _data.length; i < len; i++) {
|
|||
|
if (isObject(_data[i])) {
|
|||
|
added.push(addObject(_data[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
return added
|
|||
|
}
|
|||
|
|
|||
|
function search (crit) {
|
|||
|
if (!crit) {
|
|||
|
return []
|
|||
|
}
|
|||
|
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
|
|||
|
}
|
|||
|
|
|||
|
function __setOptions_4 (_opt) {
|
|||
|
opt = _opt || {}
|
|||
|
|
|||
|
opt.fuzzy = _opt.fuzzy || false
|
|||
|
opt.limit = _opt.limit || 10
|
|||
|
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = _opt.sort || NoSort
|
|||
|
opt.exclude = _opt.exclude || []
|
|||
|
}
|
|||
|
|
|||
|
function findMatches (data, crit, strategy, opt) {
|
|||
|
const matches = []
|
|||
|
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
|
|||
|
const match = findMatchesInObject(data[i], crit, strategy, opt)
|
|||
|
if (match) {
|
|||
|
matches.push(match)
|
|||
|
}
|
|||
|
}
|
|||
|
return matches
|
|||
|
}
|
|||
|
|
|||
|
function findMatchesInObject (obj, crit, strategy, opt) {
|
|||
|
for (const key in obj) {
|
|||
|
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
|
|||
|
return obj
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isExcluded (term, excludedTerms) {
|
|||
|
for (let i = 0, len = excludedTerms.length; i < len; i++) {
|
|||
|
const excludedTerm = excludedTerms[i]
|
|||
|
if (new RegExp(excludedTerm).test(term)) {
|
|||
|
return true
|
|||
|
}
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
/* globals ActiveXObject:false */
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$JSONLoader_2 = {
|
|||
|
load: load
|
|||
|
}
|
|||
|
|
|||
|
function load (location, callback) {
|
|||
|
const xhr = getXHR()
|
|||
|
xhr.open('GET', location, true)
|
|||
|
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
|
|||
|
xhr.send()
|
|||
|
}
|
|||
|
|
|||
|
function createStateChangeListener (xhr, callback) {
|
|||
|
return function () {
|
|||
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
|||
|
try {
|
|||
|
callback(null, JSON.parse(xhr.responseText))
|
|||
|
} catch (err) {
|
|||
|
callback(err, null)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function getXHR () {
|
|||
|
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$OptionsValidator_3 = function OptionsValidator (params) {
|
|||
|
if (!validateParams(params)) {
|
|||
|
throw new Error('-- OptionsValidator: required options missing')
|
|||
|
}
|
|||
|
|
|||
|
if (!(this instanceof OptionsValidator)) {
|
|||
|
return new OptionsValidator(params)
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = params.required
|
|||
|
|
|||
|
this.getRequiredOptions = function () {
|
|||
|
return requiredOptions
|
|||
|
}
|
|||
|
|
|||
|
this.validate = function (parameters) {
|
|||
|
const errors = []
|
|||
|
requiredOptions.forEach(function (requiredOptionName) {
|
|||
|
if (typeof parameters[requiredOptionName] === 'undefined') {
|
|||
|
errors.push(requiredOptionName)
|
|||
|
}
|
|||
|
})
|
|||
|
return errors
|
|||
|
}
|
|||
|
|
|||
|
function validateParams (params) {
|
|||
|
if (!params) {
|
|||
|
return false
|
|||
|
}
|
|||
|
return typeof params.required !== 'undefined' && params.required instanceof Array
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$utils_9 = {
|
|||
|
merge: merge,
|
|||
|
isJSON: isJSON
|
|||
|
}
|
|||
|
|
|||
|
function merge (defaultParams, mergeParams) {
|
|||
|
const mergedOptions = {}
|
|||
|
for (const option in defaultParams) {
|
|||
|
mergedOptions[option] = defaultParams[option]
|
|||
|
if (typeof mergeParams[option] !== 'undefined') {
|
|||
|
mergedOptions[option] = mergeParams[option]
|
|||
|
}
|
|||
|
}
|
|||
|
return mergedOptions
|
|||
|
}
|
|||
|
|
|||
|
function isJSON (json) {
|
|||
|
try {
|
|||
|
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
} catch (err) {
|
|||
|
return false
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var _$src_8 = {};
|
|||
|
(function (window) {
|
|||
|
'use strict'
|
|||
|
|
|||
|
let options = {
|
|||
|
searchInput: null,
|
|||
|
resultsContainer: null,
|
|||
|
json: [],
|
|||
|
success: Function.prototype,
|
|||
|
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
|
|||
|
templateMiddleware: Function.prototype,
|
|||
|
sortMiddleware: function () {
|
|||
|
return 0
|
|||
|
},
|
|||
|
noResultsText: 'No results found',
|
|||
|
limit: 10,
|
|||
|
fuzzy: false,
|
|||
|
debounceTime: null,
|
|||
|
exclude: []
|
|||
|
}
|
|||
|
|
|||
|
let debounceTimerHandle
|
|||
|
const debounce = function (func, delayMillis) {
|
|||
|
if (delayMillis) {
|
|||
|
clearTimeout(debounceTimerHandle)
|
|||
|
debounceTimerHandle = setTimeout(func, delayMillis)
|
|||
|
} else {
|
|||
|
func.call()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
|
|||
|
|
|||
|
/* removed: const _$Templater_7 = require('./Templater') */;
|
|||
|
/* removed: const _$Repository_4 = require('./Repository') */;
|
|||
|
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
|
|||
|
const optionsValidator = _$OptionsValidator_3({
|
|||
|
required: requiredOptions
|
|||
|
})
|
|||
|
/* removed: const _$utils_9 = require('./utils') */;
|
|||
|
|
|||
|
window.SimpleJekyllSearch = function (_options) {
|
|||
|
const errors = optionsValidator.validate(_options)
|
|||
|
if (errors.length > 0) {
|
|||
|
throwError('You must specify the following required options: ' + requiredOptions)
|
|||
|
}
|
|||
|
|
|||
|
options = _$utils_9.merge(options, _options)
|
|||
|
|
|||
|
_$Templater_7.setOptions({
|
|||
|
template: options.searchResultTemplate,
|
|||
|
middleware: options.templateMiddleware
|
|||
|
})
|
|||
|
|
|||
|
_$Repository_4.setOptions({
|
|||
|
fuzzy: options.fuzzy,
|
|||
|
limit: options.limit,
|
|||
|
sort: options.sortMiddleware,
|
|||
|
exclude: options.exclude
|
|||
|
})
|
|||
|
|
|||
|
if (_$utils_9.isJSON(options.json)) {
|
|||
|
initWithJSON(options.json)
|
|||
|
} else {
|
|||
|
initWithURL(options.json)
|
|||
|
}
|
|||
|
|
|||
|
const rv = {
|
|||
|
search: search
|
|||
|
}
|
|||
|
|
|||
|
typeof options.success === 'function' && options.success.call(rv)
|
|||
|
return rv
|
|||
|
}
|
|||
|
|
|||
|
function initWithJSON (json) {
|
|||
|
_$Repository_4.put(json)
|
|||
|
registerInput()
|
|||
|
}
|
|||
|
|
|||
|
function initWithURL (url) {
|
|||
|
_$JSONLoader_2.load(url, function (err, json) {
|
|||
|
if (err) {
|
|||
|
throwError('failed to get JSON (' + url + ')')
|
|||
|
}
|
|||
|
initWithJSON(json)
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function emptyResultsContainer () {
|
|||
|
options.resultsContainer.innerHTML = ''
|
|||
|
}
|
|||
|
|
|||
|
function appendToResultsContainer (text) {
|
|||
|
options.resultsContainer.innerHTML += text
|
|||
|
}
|
|||
|
|
|||
|
function registerInput () {
|
|||
|
options.searchInput.addEventListener('input', function (e) {
|
|||
|
if (isWhitelistedKey(e.which)) {
|
|||
|
emptyResultsContainer()
|
|||
|
debounce(function () { search(e.target.value) }, options.debounceTime)
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function search (query) {
|
|||
|
if (isValidQuery(query)) {
|
|||
|
emptyResultsContainer()
|
|||
|
render(_$Repository_4.search(query), query)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function render (results, query) {
|
|||
|
const len = results.length
|
|||
|
if (len === 0) {
|
|||
|
return appendToResultsContainer(options.noResultsText)
|
|||
|
}
|
|||
|
for (let i = 0; i < len; i++) {
|
|||
|
results[i].query = query
|
|||
|
appendToResultsContainer(_$Templater_7.compile(results[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isValidQuery (query) {
|
|||
|
return query && query.length > 0
|
|||
|
}
|
|||
|
|
|||
|
function isWhitelistedKey (key) {
|
|||
|
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
|
|||
|
}
|
|||
|
|
|||
|
function throwError (message) {
|
|||
|
throw new Error('SimpleJekyllSearch --- ' + message)
|
|||
|
}
|
|||
|
})(window)
|
|||
|
|
|||
|
}());
|
|||
|
</script>
|
|||
|
|
|||
|
<!-- Configuration -->
|
|||
|
<script>
|
|||
|
SimpleJekyllSearch({
|
|||
|
searchInput: document.getElementById('search-input'),
|
|||
|
resultsContainer: document.getElementById('results-container'),
|
|||
|
json: '/search.json',
|
|||
|
//searchResultTemplate: '<li><a href="https://static.rnmkcy.eu{url}">{date} {title}</a></li>'
|
|||
|
searchResultTemplate: '<li><a href="{url}">{date} {title}</a></li>'
|
|||
|
})
|
|||
|
</script>
|
|||
|
<!-- Fin déclaration champ de recherche --></div><nav class="navigation">
|
|||
|
<ul><li class="navigation__item"><a href="/archive.html">Etiquettes</a></li><li class="navigation__item"><a href="/htmldoc.html">Documents</a></li><li class="navigation__item"><a href="/liens_ttrss.html">Liens</a></li><li class="navigation__item"><a href="/aide-jekyll-text-theme.html">Aide</a></li></ul>
|
|||
|
</nav></div>
|
|||
|
</header>
|
|||
|
|
|||
|
</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">
|
|||
|
<div class="col-main cell cell--auto"><!-- start custom main top snippet --><div id="results-container" class="search-result js-search-result"></div><!-- end custom main top snippet -->
|
|||
|
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1 style="color:Tomato;">OpenLDAP installation et configuration annuaire</h1></header></div><meta itemprop="headline" content="OpenLDAP installation et configuration annuaire"><div class="article__info clearfix"><ul class="left-col menu"><li>
|
|||
|
<a class="button button--secondary button--pill button--sm"
|
|||
|
href="/archive.html?tag=debian">debian</a>
|
|||
|
</li></ul><ul class="right-col menu"><li>
|
|||
|
<i class="far fa-calendar-alt"></i> <span title="Création" style="color:#FF00FF"> 5 oct. 2019</span>
|
|||
|
|
|||
|
<span title="Modification" style="color:#00FF7F">10 oct. 2019</span></li></ul></div><meta itemprop="datePublished" content="2019-10-10T00:00:00+02:00">
|
|||
|
<meta itemprop="keywords" content="debian"><div class="js-article-content">
|
|||
|
<div class="layout--article"><!-- start custom article top snippet -->
|
|||
|
<style>
|
|||
|
#myBtn {
|
|||
|
display: none;
|
|||
|
position: fixed;
|
|||
|
bottom: 10px;
|
|||
|
right: 10px;
|
|||
|
z-index: 99;
|
|||
|
font-size: 12px;
|
|||
|
font-weight: bold;
|
|||
|
border: none;
|
|||
|
outline: none;
|
|||
|
background-color: white;
|
|||
|
color: black;
|
|||
|
cursor: pointer;
|
|||
|
padding: 5px;
|
|||
|
border-radius: 4px;
|
|||
|
}
|
|||
|
|
|||
|
#myBtn:hover {
|
|||
|
background-color: #555;
|
|||
|
}
|
|||
|
</style>
|
|||
|
|
|||
|
<button onclick="topFunction()" id="myBtn" title="Haut de page">⇧</button>
|
|||
|
|
|||
|
<script>
|
|||
|
//Get the button
|
|||
|
var mybutton = document.getElementById("myBtn");
|
|||
|
|
|||
|
// When the user scrolls down 20px from the top of the document, show the button
|
|||
|
window.onscroll = function() {scrollFunction()};
|
|||
|
|
|||
|
function scrollFunction() {
|
|||
|
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
|
|||
|
mybutton.style.display = "block";
|
|||
|
} else {
|
|||
|
mybutton.style.display = "none";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// When the user clicks on the button, scroll to the top of the document
|
|||
|
function topFunction() {
|
|||
|
document.body.scrollTop = 0;
|
|||
|
document.documentElement.scrollTop = 0;
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
|
|||
|
<!-- end custom article top snippet -->
|
|||
|
<div class="article__content" itemprop="articleBody"><details>
|
|||
|
<summary><b>Afficher/cacher Sommaire</b></summary>
|
|||
|
<!-- affichage sommaire -->
|
|||
|
<div class="toc-aside js-toc-root"></div>
|
|||
|
</details><h1 id="openldap-debian">OpenLDAP Debian</h1>
|
|||
|
|
|||
|
<p><img src="/images/OpenLDAP-logo.png" alt="" /></p>
|
|||
|
|
|||
|
<h2 id="liens">Liens</h2>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><a href="https://www.vennedey.net/resources/0-Getting-started-with-OpenLDAP-on-Debian-8">Getting started with OpenLDAP on Debian </a></li>
|
|||
|
<li><a href="https://www.vennedey.net/resources/2-LDAP-managed-mail-server-with-Postfix-and-Dovecot-for-multiple-domains">LDAP managed mail server with Postfix and Dovecot for multiple domains</a></li>
|
|||
|
<li><a href="https://wiki.gandi.net/fr/hosting/using-linux/tutorials/debian/mail-server-ldap">Installation d’un serveur mail avec backend OpenLDAP</a></li>
|
|||
|
<li>
|
|||
|
<p><a href="https://computingforgeeks.com/how-to-install-and-configure-openldap-server-on-debian/">How To Install and Configure OpenLDAP Server on Debian 10 (Buster)</a></p>
|
|||
|
</li>
|
|||
|
<li><a href="http://idum.fr/spip.php?article326">Mise en place de OpenLDAP</a> (<em>Le but de cet article est de vous faire découvrir OpenLDAP. En commençant par vous expliquer comment il fonctionne. Puis comment l’installer. Et enfin comment l’administrer.<br />
|
|||
|
Pour nous aider dans cette dernière partie, j’utiliserai l’interface web phpldapadmin.</em>)<br />
|
|||
|
<a href="/files/Mise en place de OpenLDAP.pdf">Mise en place de OpenLDAP</a> (Document au format PDF)</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h2 id="openldap-serveur">OpenLDAP Serveur</h2>
|
|||
|
|
|||
|
<p><em>Les tests sont effectués sur le serveur cinay.eu</em></p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><a href="404.html">OVH VPS SSD 1 KVM OpenStack (1 vCore/2GoRam/20GoSSD) domaine cinay.eu + compilation OpenResty</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Avant de commencer l’installation, configurez le nom d’hôte FQDN de votre serveur et ajoutez un enregistrement au fichier <strong>/etc/hosts</strong><br />
|
|||
|
Relever l’adresse ip de votre serveur <code class="language-plaintext highlighter-rouge">ip a</code> (ici notre adresse ip 192.168.0.45)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "192.168.0.45 ldap.cinay.eu" | sudo tee -a /etc/hosts
|
|||
|
sudo hostnamectl set-hostname ldap.cinay.eu --static
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="installation">Installation</h3>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>en mode su ou sudo</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>L’installation d’OpenLDAP sur Debian est faite à l’aide de la gestion des paquets APT.<br />
|
|||
|
Le premier élément précise que l’installation du paquet <strong>slapd</strong> se fait en mode non interactif et <code class="language-plaintext highlighter-rouge">-yq</code> ajoute l’installation en mode silencieux.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>DEBIAN_FRONTEND=noninteractive apt-get -yq install slapd ldap-utils net-tools
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Pendant l’installation, vous devrez choisir un mot de passe de l’administrateur pour le compte racine LDAP. rhTJH8f97dkS65</p>
|
|||
|
|
|||
|
<h3 id="configuration-initiale">Configuration initiale</h3>
|
|||
|
|
|||
|
<p>Créer un squelette de configuration pour <strong>slapd</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dpkg-reconfigure slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Voulez-vous omettre la configuration d’OpenLDAP ? Non<br />
|
|||
|
Nom de domaine : xoyize.xyz<br />
|
|||
|
Nom d’entité (« organization ») : srvxo
|
|||
|
Mot de passe de l’administrateur : ZAYz4zCGs5kb<br />
|
|||
|
Module de base de données à utiliser : MDB<br />
|
|||
|
Faut-il supprimer la base de données lors de la purge du paquet ? Non<br />
|
|||
|
Faut-il déplacer l’ancienne base de données ? Oui</p>
|
|||
|
|
|||
|
<h3 id="tests-fonctionnels">Tests fonctionnels</h3>
|
|||
|
|
|||
|
<p>Activer au démarrage et lancer <strong>slapd</strong> .</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl enable slapd
|
|||
|
systemctl start slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Sur quel port du réseau écoute slapd</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>netstat -laputn | grep slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tcp 0 0 0.0.0.0:389 0.0.0.0:* LISTEN 10204/slapd
|
|||
|
tcp6 0 0 :::389 :::* LISTEN 10204/slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Comme on peut le voir, <strong>slapd</strong> attend les requêtes ldap sur le port TCP 389.<br />
|
|||
|
Avec quels arguments s’exécute le service.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat /var/run/slapd/slapd.args
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/usr/sbin/slapd -h ldap:/// ldapi:/// -g openldap -u openldap -F /etc/ldap/slapd.d
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>-h</strong> → les modalités d’accès à slapd : ldap et ldapi (ldap via TCP 389 et ldapi via socket unix)<br />
|
|||
|
<strong>-g</strong> et <strong>-u</strong> → identité groupe et utilisateur sur lequel “tourne” le processus slapd<br />
|
|||
|
<strong>-F</strong> → emplacement du ficher de configuration de slapd</p>
|
|||
|
|
|||
|
<p>Afficher les données de l’annuaire</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapsearch -x -H ldap://xoyize.xyz -b 'dc=xoyize,dc=xyz'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># extended LDIF
|
|||
|
#
|
|||
|
# LDAPv3
|
|||
|
# base <dc=xoyize,dc=xyz> with scope subtree
|
|||
|
# filter: (objectclass=*)
|
|||
|
# requesting: ALL
|
|||
|
#
|
|||
|
|
|||
|
# search result
|
|||
|
search: 2
|
|||
|
result: 32 No such object
|
|||
|
|
|||
|
# numResponses: 1
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>-x</strong> → nous utilisons un compte défini à l’intérieur de la base pour accéder à l’annuaire<br />
|
|||
|
<strong>-H</strong> → accès en ldap sur la machine xoyize.xyz<br />
|
|||
|
<strong>-b</strong> → la racine à parcourir , ici ‘dc=xoyize,dc=xyz’</p>
|
|||
|
|
|||
|
<p>Définir un répertoire de configuration</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
mkdir -p /root/ldap/xoyize.xyz
|
|||
|
cd /root/ldap/xoyize.xyz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créer un fichier /root/pwdldap et y mettre le mot de passe administrateur</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo -n "mdpadmin" > /root/pwdldap
|
|||
|
chmod 600 /root/pwdldap
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Pour éviter la saisie du mot de passe on remplace l’option <strong>-W</strong> par <strong>-y /root/pwdldap</strong></p>
|
|||
|
|
|||
|
<h3 id="peuplement-de-lannuaire">Peuplement de l’annuaire</h3>
|
|||
|
|
|||
|
<p>Peupler l’annuaire en créant les deux <strong>OU</strong> puis un compte système avec son groupe primaire.<br />
|
|||
|
Créer un fichier au format LDIF (LDAP Data Interchange Format)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat > ou.ldif << EOF
|
|||
|
dn: ou=posixaccounts,dc=xoyize,dc=xyz
|
|||
|
objectclass: OrganizationalUnit
|
|||
|
|
|||
|
dn: ou=posixgroups,dc=xoyize,dc=xyz
|
|||
|
objectclass: OrganizationalUnit
|
|||
|
|
|||
|
EOF
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Nous avons les deux OU</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><strong>posixaccounts</strong> qui va contenir les comptes UNIX</li>
|
|||
|
<li><strong>posixgroups</strong> qui va contenir les groupes UNIX</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Ajouter à l’annuaire</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapadd -x -H ldap://xoyize.xyz -D 'cn=admin,dc=xoyize,dc=xyz' -y /root/pwdldap -f ou.ldif
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>-D</strong> → précise quel compte on va utiliser pour se connecter à slapd (ici, l’administrateur)<br />
|
|||
|
<strong>-W</strong> → pour la demande du mot de passe associé ou <strong>-y /root/pwdldap</strong>
|
|||
|
<strong>-f</strong> → le fichier .ldif</p>
|
|||
|
|
|||
|
<p>Ajouter le compte avec le groupe primaire (yanspm mp yansmm49450)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat > userandupg.ldif << EOF
|
|||
|
dn: uid=yanspm, ou=posixaccounts,dc=xoyize,dc=xyz
|
|||
|
uid: yanspm
|
|||
|
sn: yanspm
|
|||
|
homeDirectory: /home/yanspm
|
|||
|
cn: yanspm
|
|||
|
objectClass: inetOrgPerson
|
|||
|
objectClass: posixAccount
|
|||
|
objectClass: top
|
|||
|
loginShell: /bin/bash
|
|||
|
uidNumber: 6001
|
|||
|
gidNumber: 6001
|
|||
|
gecos: yan
|
|||
|
mail: yanspm@cinay.xyz
|
|||
|
userPassword: {SSHA}gzJOGEJ/fLvyp1g8zdOSGcJQZjSRukE5
|
|||
|
|
|||
|
dn: cn=yanspm,ou=posixgroups,dc=xoyize,dc=xyz
|
|||
|
objectClass: posixGroup
|
|||
|
objectClass: top
|
|||
|
gidNumber: 6001
|
|||
|
cn: yanspm
|
|||
|
|
|||
|
EOF
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Pour créer l’empreinte du mot de passe</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>slappasswd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>New password:
|
|||
|
Re-enter new password:
|
|||
|
{SSHA}gzJOGEJ/fLvyp1g8zdOSGcJQZjSRukE5
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ajout des 2 objets</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapadd -x -H ldap://xoyize.xyz -D 'cn=admin,dc=xoyize,dc=xyz' -f userandupg.ldif -W
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Enter LDAP Password:
|
|||
|
adding new entry "uid=yanspm, ou=posixaccounts,dc=xoyize,dc=xyz"
|
|||
|
|
|||
|
adding new entry "cn=yanspm,ou=posixgroups,dc=xoyize,dc=xyz"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="sécuriser-avec-ssl">Sécuriser avec SSL</h3>
|
|||
|
|
|||
|
<p>SSL, couche additionnelle à TCP qui chiffre les échanges.<br />
|
|||
|
On va activer ldaps et modifier les paramètres de lancement du service et générer un certificat.</p>
|
|||
|
|
|||
|
<h4 id="création-des-certificats">Création des certificats</h4>
|
|||
|
|
|||
|
<p>Création du répertoire ssl</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir /etc/ldap/ssl && cd /etc/ldap/ssl
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Générer certificat autosigné</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 3650 -nodes
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Generating a RSA private key
|
|||
|
.................................++++
|
|||
|
..................................................++++
|
|||
|
writing new private key to 'key.pem'
|
|||
|
-----
|
|||
|
You are about to be asked to enter information that will be incorporated
|
|||
|
into your certificate request.
|
|||
|
What you are about to enter is what is called a Distinguished Name or a DN.
|
|||
|
There are quite a few fields but you can leave some blank
|
|||
|
For some fields there will be a default value,
|
|||
|
If you enter '.', the field will be left blank.
|
|||
|
-----
|
|||
|
Country Name (2 letter code) [AU]:FR
|
|||
|
State or Province Name (full name) [Some-State]:Pays de Loire
|
|||
|
Locality Name (eg, city) []:SMM
|
|||
|
Organization Name (eg, company) [Internet Widgits Pty Ltd]:home
|
|||
|
Organizational Unit Name (eg, section) []:
|
|||
|
Common Name (e.g. server FQDN or YOUR name) []:xoyize.xyz
|
|||
|
Email Address []:
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le seul champ important : <strong>Common Name</strong></p>
|
|||
|
|
|||
|
<p>Changer les permissions sur les 2 fichiers pour appartenir à l’utilisateur <em>openldap</em></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chown openldap:openldap /etc/ldap/ssl/key.pem
|
|||
|
chown openldap:openldap /etc/ldap/ssl/cert.pem
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Clé privée accessible par root uniquement</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod 400 /etc/ldap/ssl/key.pem
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h4 id="configuration-de-slapd">Configuration de slapd</h4>
|
|||
|
|
|||
|
<p>Ajout de 2 directives pour trouver le couple clé/certificat</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat > cert.ldif << EOF
|
|||
|
dn: cn=config
|
|||
|
changetype: modify
|
|||
|
replace: olcTLSCACertificateFile
|
|||
|
olcTLSCACertificateFile: /etc/ldap/ssl/cert.pem
|
|||
|
-
|
|||
|
replace: olcTLSCertificateFile
|
|||
|
olcTLSCertificateFile: /etc/ldap/ssl/cert.pem
|
|||
|
-
|
|||
|
replace: olcTLSCertificateKeyFile
|
|||
|
olcTLSCertificateKeyFile: /etc/ldap/ssl/key.pem
|
|||
|
|
|||
|
EOF
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Pour appliquer les modifications ,nous allons passer par le mode ldapi car il n’y a pas de compte administrateur associé à la racine cn=config</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapmodify -Y EXTERNAL -H ldapi:/// -f cert.ldif
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SASL/EXTERNAL authentication started
|
|||
|
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
|
|||
|
SASL SSF: 0
|
|||
|
create: 2019-10-05
|
|||
|
modifying entry "cn=config"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Argument <strong>-x</strong> a disparu au profit de <strong>-Y EXTERNAL</strong> pour une authentification via l’UID<br />
|
|||
|
L’option <strong>-H</strong> a pour valeur ldapi:/// qui pointe sur le socket UNIX géré par slapd</p>
|
|||
|
|
|||
|
<p>Dernière étape, modifier le fichier <strong>/etc/default/slapd</strong> pour lui indiquer qu’il doit gérer la méthode d’accès ldaps</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/default/slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SLAPD_SERVICES="ldap:/// ldapi:/// ldaps:///"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Relancer slapd</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérification</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>netstat -laputn | grep slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tcp 0 0 0.0.0.0:636 0.0.0.0:* LISTEN 23197/slapd
|
|||
|
tcp 0 0 0.0.0.0:389 0.0.0.0:* LISTEN 23197/slapd
|
|||
|
tcp6 0 0 :::636 :::* LISTEN 23197/slapd
|
|||
|
tcp6 0 0 :::389 :::* LISTEN 23197/slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Nous avons le service slapd en écoute SSL sur le port 636</p>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p><strong>ATTENTION , si parefeu , ouvrir en entrée le port TCP 636 IPV4/IPV6</strong></p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h2 id="openldap-php-sur-serveur">OpenLDAP PHP sur serveur</h2>
|
|||
|
|
|||
|
<p>Installer le module</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install php7.3-ldpa
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Fichiers de test</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/var/www/test.php
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span>
|
|||
|
<span class="nv">$baseDN</span> <span class="o">=</span> <span class="s2">"dc=ldap,dc=cinay,dc=eu"</span><span class="p">;</span>
|
|||
|
<span class="nv">$ldapServer</span> <span class="o">=</span> <span class="s2">"ldap.cinay.eu"</span><span class="p">;</span>
|
|||
|
<span class="nv">$ldapServerPort</span> <span class="o">=</span> <span class="mi">389</span><span class="p">;</span>
|
|||
|
<span class="nv">$rdn</span><span class="o">=</span><span class="s2">"admin"</span><span class="p">;</span>
|
|||
|
<span class="nv">$mdp</span><span class="o">=</span><span class="s2">"f43z7C9TBwxX3h"</span><span class="p">;</span>
|
|||
|
<span class="nv">$dn</span> <span class="o">=</span> <span class="s1">'cn=admin,dc=ldap,dc=cinay,dc=eu'</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="k">echo</span> <span class="s2">"Connexion au serveur <br />"</span><span class="p">;</span>
|
|||
|
<span class="nv">$conn</span><span class="o">=</span><span class="nb">ldap_connect</span><span class="p">(</span><span class="nv">$ldapServer</span><span class="p">);</span>
|
|||
|
|
|||
|
<span class="c1">// on teste : le serveur LDAP est-il trouvé ?</span>
|
|||
|
<span class="k">if</span> <span class="p">(</span><span class="nv">$conn</span><span class="p">)</span> <span class="p">{</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"Le résultat de connexion est "</span><span class="mf">.</span><span class="nv">$conn</span> <span class="mf">.</span><span class="s2">"<br />"</span><span class="p">;</span>
|
|||
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|||
|
<span class="k">die</span><span class="p">(</span><span class="s2">"connexion impossible au serveur LDAP"</span><span class="p">);</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c1">// 2ème étape : on effectue une liaison au serveur, ici de type "anonyme"</span>
|
|||
|
<span class="c1">// pour une recherche permise par un accès en lecture seule</span>
|
|||
|
|
|||
|
<span class="c1">// On dit qu'on utilise LDAP V3, sinon la V2 par défaut est utilisé</span>
|
|||
|
<span class="c1">// et le bind ne passe pas. </span>
|
|||
|
<span class="k">if</span> <span class="p">(</span><span class="nb">ldap_set_option</span><span class="p">(</span><span class="nv">$conn</span><span class="p">,</span> <span class="no">LDAP_OPT_PROTOCOL_VERSION</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span> <span class="p">{</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"Utilisation de LDAPv3 <br />"</span><span class="p">;</span>
|
|||
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"Impossible d'utiliser LDAP V3<br />"</span><span class="p">;</span>
|
|||
|
<span class="k">exit</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c1">// Instruction de liaison. </span>
|
|||
|
<span class="c1">// Décommenter la ligne pour une connexion authentifiée</span>
|
|||
|
<span class="c1">// ou pour une connexion anonyme.</span>
|
|||
|
<span class="c1">// Connexion authentifiée</span>
|
|||
|
<span class="k">print</span> <span class="p">(</span><span class="s2">"Connexion authentifiée ...<br />"</span><span class="p">);</span>
|
|||
|
<span class="nv">$bindServerLDAP</span><span class="o">=</span><span class="nb">ldap_bind</span><span class="p">(</span><span class="nv">$conn</span><span class="p">,</span><span class="nv">$dn</span><span class="p">,</span><span class="nv">$mdp</span><span class="p">);</span>
|
|||
|
<span class="c1">// print ("Connexion anonyme...<br />");</span>
|
|||
|
<span class="c1">// $bindServerLDAP=ldap_bind($conn);</span>
|
|||
|
|
|||
|
<span class="k">echo</span> <span class="s2">"Liaison au serveur : "</span><span class="mf">.</span> <span class="nb">ldap_error</span><span class="p">(</span><span class="nv">$conn</span><span class="p">)</span><span class="mf">.</span><span class="s2">"<br />"</span><span class="p">;</span>
|
|||
|
<span class="c1">// en cas de succès de la liaison, renvoie Vrai</span>
|
|||
|
<span class="k">if</span> <span class="p">(</span><span class="nv">$bindServerLDAP</span><span class="p">)</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"Le résultat de connexion est </span><span class="nv">$bindServerLDAP</span><span class="s2"> <br />"</span><span class="p">;</span>
|
|||
|
<span class="k">else</span>
|
|||
|
<span class="k">die</span><span class="p">(</span><span class="s2">"Liaison impossible au serveur ldap ..."</span><span class="p">);</span>
|
|||
|
|
|||
|
<span class="cm">/* 3ème étape : on effectue une recherche anonyme, avec le dn de base,
|
|||
|
* par exemple, sur tous les noms commençant par B
|
|||
|
*/</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"Recherche suivant le filtre (sn=y*) <br />"</span><span class="p">;</span>
|
|||
|
<span class="nv">$query</span> <span class="o">=</span> <span class="s2">"sn=y*"</span><span class="p">;</span>
|
|||
|
<span class="nv">$result</span><span class="o">=</span><span class="nb">ldap_search</span><span class="p">(</span><span class="nv">$conn</span><span class="p">,</span> <span class="nv">$baseDN</span><span class="p">,</span> <span class="nv">$query</span><span class="p">);</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"Le résultat de la recherche est </span><span class="nv">$result</span><span class="s2"> <br />"</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="k">echo</span> <span class="s2">"Le nombre d'entrées retournées est "</span><span class="mf">.</span><span class="nb">ldap_count_entries</span><span class="p">(</span><span class="nv">$conn</span><span class="p">,</span><span class="nv">$result</span><span class="p">)</span><span class="mf">.</span><span class="s2">"<p />"</span><span class="p">;</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"Lecture de ces entrées ....<p />"</span><span class="p">;</span>
|
|||
|
<span class="nv">$info</span> <span class="o">=</span> <span class="nb">ldap_get_entries</span><span class="p">(</span><span class="nv">$conn</span><span class="p">,</span> <span class="nv">$result</span><span class="p">);</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"Données pour "</span><span class="mf">.</span><span class="nv">$info</span><span class="p">[</span><span class="s2">"count"</span><span class="p">]</span><span class="mf">.</span><span class="s2">" entrées:<p />"</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="k">for</span> <span class="p">(</span><span class="nv">$i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nv">$i</span> <span class="o"><</span> <span class="nv">$info</span><span class="p">[</span><span class="s2">"count"</span><span class="p">];</span> <span class="nv">$i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"dn est : "</span><span class="mf">.</span> <span class="nv">$info</span><span class="p">[</span><span class="nv">$i</span><span class="p">][</span><span class="s2">"cn"</span><span class="p">]</span> <span class="mf">.</span><span class="s2">"<br />"</span><span class="p">;</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"premiere entree cn : "</span><span class="mf">.</span> <span class="nv">$info</span><span class="p">[</span><span class="nv">$i</span><span class="p">][</span><span class="s2">"cn"</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="mf">.</span><span class="s2">"<br />"</span><span class="p">;</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"premier email : "</span><span class="mf">.</span> <span class="nv">$info</span><span class="p">[</span><span class="nv">$i</span><span class="p">][</span><span class="s2">"mail"</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="mf">.</span><span class="s2">"<p />"</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c1">// Test utilisateur mot de passe</span>
|
|||
|
<span class="k">if</span><span class="p">(</span><span class="nv">$bindServerLDAP</span> <span class="o">=</span> <span class="o">@</span><span class="nb">ldap_bind</span><span class="p">(</span><span class="nv">$conn</span><span class="p">,</span> <span class="s2">"uid=yanspm,ou=posixaccounts,dc=ldap,dc=cinay,dc=eu"</span><span class="p">,</span> <span class="s2">"yansmm49450"</span><span class="p">))</span> <span class="p">{</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"OK Test utilisateur mot de passe <br />"</span><span class="p">;</span>
|
|||
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"ERROR Test utilisateur mot de passe <br />"</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<span class="k">echo</span> <span class="s2">"Fermeture de la connexion"</span><span class="p">;</span>
|
|||
|
<span class="nb">ldap_close</span><span class="p">(</span><span class="nv">$conn</span><span class="p">);</span>
|
|||
|
|
|||
|
|
|||
|
<span class="cp">?></span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Résultat</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Connexion au serveur
|
|||
|
Le résultat de connexion est Resource id #2
|
|||
|
Utilisation de LDAPv3
|
|||
|
Connexion authentifiée ...
|
|||
|
Liaison au serveur : Success
|
|||
|
Le résultat de connexion est 1
|
|||
|
Recherche suivant le filtre (sn=y*)
|
|||
|
Le résultat de la recherche est Resource id #3
|
|||
|
Le nombre d'entrées retournées est 1
|
|||
|
|
|||
|
Lecture de ces entrées ....
|
|||
|
|
|||
|
Données pour 1 entrées:
|
|||
|
|
|||
|
dn est : Array
|
|||
|
premiere entree cn : yanspm
|
|||
|
premier email : yanspm@cinay.xyz
|
|||
|
|
|||
|
OK Test utilisateur mot de passe
|
|||
|
Fermeture de la connexion
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/var/www/test1.php
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span>
|
|||
|
<span class="c1">//pour les tests</span>
|
|||
|
<span class="nv">$user</span> <span class="o">=</span> <span class="s2">"yanspm"</span><span class="p">;</span>
|
|||
|
<span class="nv">$password</span><span class="o">=</span><span class="s2">"yansmm49450"</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="c1">// annuaire ldap</span>
|
|||
|
<span class="nv">$ldap_host</span> <span class="o">=</span> <span class="s2">"ldap.cinay.eu"</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="c1">// connexion annuaire</span>
|
|||
|
<span class="nv">$ldap</span> <span class="o">=</span> <span class="nb">ldap_connect</span><span class="p">(</span><span class="nv">$ldap_host</span><span class="p">);</span>
|
|||
|
|
|||
|
<span class="c1">// on teste : le serveur LDAP est-il trouvé ?</span>
|
|||
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$ldap</span><span class="p">)</span> <span class="p">{</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"Erreur connexion ...<br />"</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c1">// configure ldap params</span>
|
|||
|
<span class="nb">ldap_set_option</span><span class="p">(</span><span class="nv">$ldap</span><span class="p">,</span><span class="no">LDAP_OPT_PROTOCOL_VERSION</span><span class="p">,</span><span class="mi">3</span><span class="p">);</span>
|
|||
|
<span class="k">print</span> <span class="p">(</span><span class="s2">"Connexion anonyme...<br />"</span><span class="p">);</span>
|
|||
|
<span class="nv">$bindServerLDAP</span><span class="o">=</span><span class="nb">ldap_bind</span><span class="p">(</span><span class="nv">$ldap</span><span class="p">);</span>
|
|||
|
|
|||
|
<span class="k">echo</span> <span class="s2">"Liaison au serveur : "</span><span class="mf">.</span> <span class="nb">ldap_error</span><span class="p">(</span><span class="nv">$conn</span><span class="p">)</span><span class="mf">.</span><span class="s2">"<br />"</span><span class="p">;</span>
|
|||
|
<span class="c1">// en cas de succès de la liaison, renvoie Vrai</span>
|
|||
|
<span class="k">if</span> <span class="p">(</span><span class="nv">$bindServerLDAP</span><span class="p">)</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"Le résultat de connexion est </span><span class="nv">$bindServerLDAP</span><span class="s2"> <br />"</span><span class="p">;</span>
|
|||
|
<span class="k">else</span>
|
|||
|
<span class="k">die</span><span class="p">(</span><span class="s2">"Liaison impossible au serveur ldap ..."</span><span class="p">);</span>
|
|||
|
|
|||
|
<span class="c1">// Test utilisateur mot de passe</span>
|
|||
|
<span class="k">if</span><span class="p">(</span><span class="nv">$bindServerLDAP</span> <span class="o">=</span> <span class="o">@</span><span class="nb">ldap_bind</span><span class="p">(</span><span class="nv">$ldap</span><span class="p">,</span> <span class="s2">"uid="</span><span class="mf">.</span><span class="nv">$user</span><span class="mf">.</span><span class="s2">",ou=posixaccounts,dc=ldap,dc=cinay,dc=eu"</span><span class="p">,</span> <span class="nv">$password</span><span class="p">))</span> <span class="p">{</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"OK Test utilisateur mot de passe <br />"</span><span class="p">;</span>
|
|||
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"ERROR Test utilisateur mot de passe <br />"</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
|
|||
|
<span class="cp">?></span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Page authentification</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/var/www/authenticate.php
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span>
|
|||
|
<span class="k">function</span> <span class="n">authenticate</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span> <span class="nv">$password</span><span class="p">)</span> <span class="p">{</span>
|
|||
|
|
|||
|
<span class="c1">//pour les tests</span>
|
|||
|
<span class="c1">//$user = "yanspm";</span>
|
|||
|
<span class="c1">//$password="yansmm49450";</span>
|
|||
|
|
|||
|
<span class="k">if</span><span class="p">(</span><span class="k">empty</span><span class="p">(</span><span class="nv">$user</span><span class="p">)</span> <span class="o">||</span> <span class="k">empty</span><span class="p">(</span><span class="nv">$password</span><span class="p">))</span> <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
|
|||
|
<span class="c1">// annuaire ldap</span>
|
|||
|
<span class="nv">$ldap_host</span> <span class="o">=</span> <span class="s2">"ldap.cinay.eu"</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="c1">// connexion annuaire</span>
|
|||
|
<span class="nv">$ldap</span> <span class="o">=</span> <span class="nb">ldap_connect</span><span class="p">(</span><span class="nv">$ldap_host</span><span class="p">);</span>
|
|||
|
|
|||
|
<span class="c1">// on teste : le serveur LDAP est-il trouvé ?</span>
|
|||
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$ldap</span><span class="p">)</span> <span class="p">{</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"Erreur connexion ...<br />"</span><span class="p">;</span>
|
|||
|
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c1">// configure ldap params</span>
|
|||
|
<span class="nb">ldap_set_option</span><span class="p">(</span><span class="nv">$ldap</span><span class="p">,</span><span class="no">LDAP_OPT_PROTOCOL_VERSION</span><span class="p">,</span><span class="mi">3</span><span class="p">);</span>
|
|||
|
<span class="k">print</span> <span class="p">(</span><span class="s2">"Connexion anonyme...<br />"</span><span class="p">);</span>
|
|||
|
<span class="nv">$bindServerLDAP</span><span class="o">=</span><span class="nb">ldap_bind</span><span class="p">(</span><span class="nv">$ldap</span><span class="p">);</span>
|
|||
|
|
|||
|
<span class="k">echo</span> <span class="s2">"Liaison au serveur : "</span><span class="mf">.</span> <span class="nb">ldap_error</span><span class="p">(</span><span class="nv">$conn</span><span class="p">)</span><span class="mf">.</span><span class="s2">"<br />"</span><span class="p">;</span>
|
|||
|
<span class="c1">// en cas de succès de la liaison, renvoie Vrai</span>
|
|||
|
<span class="k">if</span> <span class="p">(</span><span class="nv">$bindServerLDAP</span><span class="p">)</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"Le résultat de connexion est </span><span class="nv">$bindServerLDAP</span><span class="s2"> <br />"</span><span class="p">;</span>
|
|||
|
<span class="k">else</span>
|
|||
|
<span class="c1">//die("Liaison impossible au serveur ldap ...");</span>
|
|||
|
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="c1">// Test utilisateur mot de passe</span>
|
|||
|
<span class="k">if</span><span class="p">(</span><span class="nv">$bindServerLDAP</span> <span class="o">=</span> <span class="o">@</span><span class="nb">ldap_bind</span><span class="p">(</span><span class="nv">$ldap</span><span class="p">,</span> <span class="s2">"uid="</span><span class="mf">.</span><span class="nv">$user</span><span class="mf">.</span><span class="s2">",ou=posixaccounts,dc=ldap,dc=cinay,dc=eu"</span><span class="p">,</span> <span class="nv">$password</span><span class="p">))</span> <span class="p">{</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"OK Test utilisateur mot de passe <br />"</span><span class="p">;</span>
|
|||
|
<span class="nv">$access</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
|
|||
|
<span class="c1">// establish session variables</span>
|
|||
|
<span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'user'</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$user</span><span class="p">;</span>
|
|||
|
<span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'access'</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$access</span><span class="p">;</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"variables ajustées <br />"</span><span class="p">;</span>
|
|||
|
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
|
|||
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|||
|
<span class="k">echo</span> <span class="s2">"ERROR Test utilisateur mot de passe <br />"</span><span class="p">;</span>
|
|||
|
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="cp">?></span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Page protection</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/var/www/protected.php
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
|
|||
|
<span class="cp"><?php</span>
|
|||
|
<span class="c1">// initialize session</span>
|
|||
|
<span class="nb">session_start</span><span class="p">();</span>
|
|||
|
|
|||
|
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'user'</span><span class="p">]))</span> <span class="p">{</span>
|
|||
|
<span class="c1">// user is not logged in, do something like redirect to login.php</span>
|
|||
|
<span class="nb">header</span><span class="p">(</span><span class="s2">"Location: login.php"</span><span class="p">);</span>
|
|||
|
<span class="k">die</span><span class="p">();</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="k">if</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'access'</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
|
|||
|
<span class="c1">// another example...</span>
|
|||
|
<span class="c1">// user is logged in but not a manager, let's stop him</span>
|
|||
|
<span class="k">die</span><span class="p">(</span><span class="s2">"Access Denied"</span><span class="p">);</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="cp">?></span>
|
|||
|
|
|||
|
<span class="nt"><p></span>Welcome <span class="cp"><?=</span> <span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'user'</span><span class="p">]</span> <span class="cp">?></span>!<span class="nt"></p></span>
|
|||
|
|
|||
|
<span class="nt"><p><strong></span>Secret Protected Content Here!<span class="nt"></strong></p></span>
|
|||
|
|
|||
|
<span class="nt"><p></span>Ceci est un test...<span class="nt"></p></span>
|
|||
|
|
|||
|
// <span class="nt"><p><a</span> <span class="na">href=</span><span class="s">"login.php?out=1"</span><span class="nt">></span>Logout<span class="nt"></a></p></span>
|
|||
|
<span class="nt"><p><a</span> <span class="na">href=</span><span class="s">"index.php?out=1"</span><span class="nt">></span>Logout<span class="nt"></a></p></span>
|
|||
|
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Page de connexion</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/var/www/index.php
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span>
|
|||
|
<span class="c1">// initialize session</span>
|
|||
|
<span class="nb">session_start</span><span class="p">();</span>
|
|||
|
|
|||
|
<span class="k">include</span><span class="p">(</span><span class="s2">"authenticate.php"</span><span class="p">);</span>
|
|||
|
|
|||
|
<span class="c1">// check to see if user is logging out</span>
|
|||
|
<span class="k">if</span><span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'out'</span><span class="p">]))</span> <span class="p">{</span>
|
|||
|
<span class="c1">// destroy session</span>
|
|||
|
<span class="nb">session_unset</span><span class="p">();</span>
|
|||
|
<span class="nv">$_SESSION</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
|
|||
|
<span class="k">unset</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'user'</span><span class="p">],</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'access'</span><span class="p">]);</span>
|
|||
|
<span class="nb">session_destroy</span><span class="p">();</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c1">// check to see if login form has been submitted</span>
|
|||
|
<span class="k">if</span><span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'userLogin'</span><span class="p">])){</span>
|
|||
|
<span class="c1">// run information through authenticator</span>
|
|||
|
<span class="k">if</span><span class="p">(</span><span class="nf">authenticate</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'userLogin'</span><span class="p">],</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'userPassword'</span><span class="p">]))</span>
|
|||
|
<span class="p">{</span>
|
|||
|
<span class="c1">// authentication passed</span>
|
|||
|
<span class="nb">header</span><span class="p">(</span><span class="s2">"Location: protected.php"</span><span class="p">);</span>
|
|||
|
<span class="k">die</span><span class="p">();</span>
|
|||
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|||
|
<span class="c1">// authentication failed</span>
|
|||
|
<span class="nv">$error</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c1">// output error to user</span>
|
|||
|
<span class="k">if</span><span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$error</span><span class="p">))</span> <span class="k">echo</span> <span class="s2">"Login failed: Incorrect user name, password, or rights<br />"</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="c1">// output logout success</span>
|
|||
|
<span class="k">if</span><span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'out'</span><span class="p">]))</span> <span class="k">echo</span> <span class="s2">"Logout successful"</span><span class="p">;</span>
|
|||
|
<span class="cp">?></span>
|
|||
|
|
|||
|
<span class="cp"><!DOCTYPE html></span>
|
|||
|
<span class="nt"><html></span>
|
|||
|
<span class="nt"><head></span>
|
|||
|
<span class="nt"><meta</span> <span class="na">name=</span><span class="s">"viewport"</span> <span class="na">content=</span><span class="s">"width=device-width, initial-scale=1"</span><span class="nt">></span>
|
|||
|
<span class="nt"><style></span>
|
|||
|
<span class="nt">body</span> <span class="p">{</span><span class="nl">font-family</span><span class="p">:</span> <span class="n">Arial</span><span class="p">,</span> <span class="n">Helvetica</span><span class="p">,</span> <span class="nb">sans-serif</span><span class="p">;}</span>
|
|||
|
|
|||
|
<span class="c">/* Full-width input fields */</span>
|
|||
|
<span class="nt">input</span><span class="o">[</span><span class="nt">type</span><span class="o">=</span><span class="nt">text</span><span class="o">],</span> <span class="nt">input</span><span class="o">[</span><span class="nt">type</span><span class="o">=</span><span class="nt">password</span><span class="o">]</span> <span class="p">{</span>
|
|||
|
<span class="nl">width</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
|
|||
|
<span class="nl">padding</span><span class="p">:</span> <span class="m">12px</span> <span class="m">20px</span><span class="p">;</span>
|
|||
|
<span class="nl">margin</span><span class="p">:</span> <span class="m">8px</span> <span class="m">0</span><span class="p">;</span>
|
|||
|
<span class="nl">display</span><span class="p">:</span> <span class="n">inline-block</span><span class="p">;</span>
|
|||
|
<span class="nl">border</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="m">#ccc</span><span class="p">;</span>
|
|||
|
<span class="nl">box-sizing</span><span class="p">:</span> <span class="n">border-box</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c">/* Set a style for all buttons */</span>
|
|||
|
<span class="nt">button</span> <span class="p">{</span>
|
|||
|
<span class="nl">background-color</span><span class="p">:</span> <span class="m">#4CAF50</span><span class="p">;</span>
|
|||
|
<span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
|
|||
|
<span class="nl">padding</span><span class="p">:</span> <span class="m">14px</span> <span class="m">20px</span><span class="p">;</span>
|
|||
|
<span class="nl">margin</span><span class="p">:</span> <span class="m">8px</span> <span class="m">0</span><span class="p">;</span>
|
|||
|
<span class="nl">border</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
|
|||
|
<span class="nl">cursor</span><span class="p">:</span> <span class="nb">pointer</span><span class="p">;</span>
|
|||
|
<span class="nl">width</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="nt">button</span><span class="nd">:hover</span> <span class="p">{</span>
|
|||
|
<span class="nl">opacity</span><span class="p">:</span> <span class="m">0.8</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c">/* Extra styles for the cancel button */</span>
|
|||
|
<span class="nc">.cancelbtn</span> <span class="p">{</span>
|
|||
|
<span class="nl">width</span><span class="p">:</span> <span class="nb">auto</span><span class="p">;</span>
|
|||
|
<span class="nl">padding</span><span class="p">:</span> <span class="m">10px</span> <span class="m">18px</span><span class="p">;</span>
|
|||
|
<span class="nl">background-color</span><span class="p">:</span> <span class="m">#f44336</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c">/* Center the image and position the close button */</span>
|
|||
|
<span class="nc">.imgcontainer</span> <span class="p">{</span>
|
|||
|
<span class="nl">text-align</span><span class="p">:</span> <span class="nb">center</span><span class="p">;</span>
|
|||
|
<span class="nl">margin</span><span class="p">:</span> <span class="m">24px</span> <span class="m">0</span> <span class="m">12px</span> <span class="m">0</span><span class="p">;</span>
|
|||
|
<span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="nt">img</span><span class="nc">.avatar</span> <span class="p">{</span>
|
|||
|
<span class="nl">width</span><span class="p">:</span> <span class="m">40%</span><span class="p">;</span>
|
|||
|
<span class="nl">border-radius</span><span class="p">:</span> <span class="m">50%</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="nc">.container</span> <span class="p">{</span>
|
|||
|
<span class="nl">padding</span><span class="p">:</span> <span class="m">16px</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="nt">span</span><span class="nc">.psw</span> <span class="p">{</span>
|
|||
|
<span class="nl">float</span><span class="p">:</span> <span class="nb">right</span><span class="p">;</span>
|
|||
|
<span class="nl">padding-top</span><span class="p">:</span> <span class="m">16px</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c">/* The Modal (background) */</span>
|
|||
|
<span class="nc">.modal</span> <span class="p">{</span>
|
|||
|
<span class="nl">display</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span> <span class="c">/* Hidden by default */</span>
|
|||
|
<span class="nl">position</span><span class="p">:</span> <span class="nb">fixed</span><span class="p">;</span> <span class="c">/* Stay in place */</span>
|
|||
|
<span class="nl">z-index</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span> <span class="c">/* Sit on top */</span>
|
|||
|
<span class="nl">left</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
|
|||
|
<span class="nl">top</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
|
|||
|
<span class="nl">width</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span> <span class="c">/* Full width */</span>
|
|||
|
<span class="nl">height</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span> <span class="c">/* Full height */</span>
|
|||
|
<span class="nl">overflow</span><span class="p">:</span> <span class="nb">auto</span><span class="p">;</span> <span class="c">/* Enable scroll if needed */</span>
|
|||
|
<span class="nl">background-color</span><span class="p">:</span> <span class="nb">rgb</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">0</span><span class="p">,</span><span class="m">0</span><span class="p">);</span> <span class="c">/* Fallback color */</span>
|
|||
|
<span class="nl">background-color</span><span class="p">:</span> <span class="n">rgba</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">0</span><span class="p">,</span><span class="m">0</span><span class="p">,</span><span class="m">0.4</span><span class="p">);</span> <span class="c">/* Black w/ opacity */</span>
|
|||
|
<span class="nl">padding-top</span><span class="p">:</span> <span class="m">60px</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c">/* Modal Content/Box */</span>
|
|||
|
<span class="nc">.modal-content</span> <span class="p">{</span>
|
|||
|
<span class="nl">background-color</span><span class="p">:</span> <span class="m">#fefefe</span><span class="p">;</span>
|
|||
|
<span class="nl">margin</span><span class="p">:</span> <span class="m">5%</span> <span class="nb">auto</span> <span class="m">15%</span> <span class="nb">auto</span><span class="p">;</span> <span class="c">/* 5% from the top, 15% from the bottom and centered */</span>
|
|||
|
<span class="nl">border</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="m">#888</span><span class="p">;</span>
|
|||
|
<span class="nl">width</span><span class="p">:</span> <span class="m">40%</span><span class="p">;</span> <span class="c">/* Could be more or less, depending on screen size */</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c">/* The Close Button (x) */</span>
|
|||
|
<span class="nc">.close</span> <span class="p">{</span>
|
|||
|
<span class="nl">position</span><span class="p">:</span> <span class="nb">absolute</span><span class="p">;</span>
|
|||
|
<span class="nl">right</span><span class="p">:</span> <span class="m">25px</span><span class="p">;</span>
|
|||
|
<span class="nl">top</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
|
|||
|
<span class="nl">color</span><span class="p">:</span> <span class="m">#000</span><span class="p">;</span>
|
|||
|
<span class="nl">font-size</span><span class="p">:</span> <span class="m">35px</span><span class="p">;</span>
|
|||
|
<span class="nl">font-weight</span><span class="p">:</span> <span class="nb">bold</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="nc">.close</span><span class="nd">:hover</span><span class="o">,</span>
|
|||
|
<span class="nc">.close</span><span class="nd">:focus</span> <span class="p">{</span>
|
|||
|
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
|
|||
|
<span class="nl">cursor</span><span class="p">:</span> <span class="nb">pointer</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c">/* Add Zoom Animation */</span>
|
|||
|
<span class="nc">.animate</span> <span class="p">{</span>
|
|||
|
<span class="nl">-webkit-animation</span><span class="p">:</span> <span class="n">animatezoom</span> <span class="m">0.6s</span><span class="p">;</span>
|
|||
|
<span class="nl">animation</span><span class="p">:</span> <span class="n">animatezoom</span> <span class="m">0.6s</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="k">@-webkit-keyframes</span> <span class="n">animatezoom</span> <span class="p">{</span>
|
|||
|
<span class="nt">from</span> <span class="p">{</span><span class="nl">-webkit-transform</span><span class="p">:</span> <span class="n">scale</span><span class="p">(</span><span class="m">0</span><span class="p">)}</span>
|
|||
|
<span class="nt">to</span> <span class="p">{</span><span class="nl">-webkit-transform</span><span class="p">:</span> <span class="n">scale</span><span class="p">(</span><span class="m">1</span><span class="p">)}</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="k">@keyframes</span> <span class="n">animatezoom</span> <span class="p">{</span>
|
|||
|
<span class="nt">from</span> <span class="p">{</span><span class="nl">transform</span><span class="p">:</span> <span class="n">scale</span><span class="p">(</span><span class="m">0</span><span class="p">)}</span>
|
|||
|
<span class="nt">to</span> <span class="p">{</span><span class="nl">transform</span><span class="p">:</span> <span class="n">scale</span><span class="p">(</span><span class="m">1</span><span class="p">)}</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c">/* Change styles for span and cancel button on extra small screens */</span>
|
|||
|
<span class="k">@media</span> <span class="n">screen</span> <span class="n">and</span> <span class="p">(</span><span class="n">max-width</span><span class="p">:</span> <span class="m">300px</span><span class="p">)</span> <span class="p">{</span>
|
|||
|
<span class="nt">span</span><span class="nc">.psw</span> <span class="p">{</span>
|
|||
|
<span class="nl">display</span><span class="p">:</span> <span class="nb">block</span><span class="p">;</span>
|
|||
|
<span class="nl">float</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="nc">.cancelbtn</span> <span class="p">{</span>
|
|||
|
<span class="nl">width</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="nt"></style></span>
|
|||
|
<span class="nt"></head></span>
|
|||
|
<span class="nt"><body></span>
|
|||
|
|
|||
|
<span class="nt"><h2></span>Modal Login Form<span class="nt"></h2></span>
|
|||
|
|
|||
|
<span class="nt"><button</span> <span class="na">onclick=</span><span class="s">"document.getElementById('id01').style.display='block'"</span> <span class="na">style=</span><span class="s">"width:auto;"</span><span class="nt">></span>Login<span class="nt"></button></span>
|
|||
|
|
|||
|
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"id01"</span> <span class="na">class=</span><span class="s">"modal"</span><span class="nt">></span>
|
|||
|
|
|||
|
<span class="nt"><form</span> <span class="na">class=</span><span class="s">"modal-content animate"</span> <span class="na">method=</span><span class="s">"post"</span><span class="nt">></span>
|
|||
|
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"imgcontainer"</span><span class="nt">></span>
|
|||
|
<span class="nt"><span</span> <span class="na">onclick=</span><span class="s">"document.getElementById('id01').style.display='none'"</span> <span class="na">class=</span><span class="s">"close"</span> <span class="na">title=</span><span class="s">"Close Modal"</span><span class="nt">></span><span class="ni">&times;</span><span class="nt"></span></span>
|
|||
|
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"img_avatar2.png"</span> <span class="na">alt=</span><span class="s">"Avatar"</span> <span class="na">class=</span><span class="s">"avatar"</span><span class="nt">></span>
|
|||
|
<span class="nt"></div></span>
|
|||
|
|
|||
|
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"container"</span><span class="nt">></span>
|
|||
|
<span class="nt"><label</span> <span class="na">for=</span><span class="s">"uname"</span><span class="nt">><b></span>Username<span class="nt"></b></label></span>
|
|||
|
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">placeholder=</span><span class="s">"Enter Username"</span> <span class="na">name=</span><span class="s">"userLogin"</span> <span class="na">required</span><span class="nt">></span>
|
|||
|
|
|||
|
<span class="nt"><label</span> <span class="na">for=</span><span class="s">"psw"</span><span class="nt">><b></span>Password<span class="nt"></b></label></span>
|
|||
|
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"password"</span> <span class="na">placeholder=</span><span class="s">"Enter Password"</span> <span class="na">name=</span><span class="s">"userPassword"</span> <span class="na">required</span><span class="nt">></span>
|
|||
|
|
|||
|
<span class="nt"><button</span> <span class="na">type=</span><span class="s">"submit"</span><span class="nt">></span>Login<span class="nt"></button></span>
|
|||
|
<span class="nt"><label></span>
|
|||
|
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"checkbox"</span> <span class="na">checked=</span><span class="s">"checked"</span> <span class="na">name=</span><span class="s">"remember"</span><span class="nt">></span> Remember me
|
|||
|
<span class="nt"></label></span>
|
|||
|
<span class="nt"></div></span>
|
|||
|
|
|||
|
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"container"</span> <span class="na">style=</span><span class="s">"background-color:#f1f1f1"</span><span class="nt">></span>
|
|||
|
<span class="nt"><button</span> <span class="na">type=</span><span class="s">"button"</span> <span class="na">onclick=</span><span class="s">"document.getElementById('id01').style.display='none'"</span> <span class="na">class=</span><span class="s">"cancelbtn"</span><span class="nt">></span>Cancel<span class="nt"></button></span>
|
|||
|
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"psw"</span><span class="nt">></span>Forgot <span class="nt"><a</span> <span class="na">href=</span><span class="s">"#"</span><span class="nt">></span>password?<span class="nt"></a></span></span>
|
|||
|
<span class="nt"></div></span>
|
|||
|
<span class="nt"></form></span>
|
|||
|
<span class="nt"></div></span>
|
|||
|
|
|||
|
<span class="nt"><script></span>
|
|||
|
<span class="c1">// Get the modal</span>
|
|||
|
<span class="kd">var</span> <span class="nx">modal</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">id01</span><span class="dl">'</span><span class="p">);</span>
|
|||
|
|
|||
|
<span class="c1">// When the user clicks anywhere outside of the modal, close it</span>
|
|||
|
<span class="nb">window</span><span class="p">.</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
|
|||
|
<span class="k">if </span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">target</span> <span class="o">==</span> <span class="nx">modal</span><span class="p">)</span> <span class="p">{</span>
|
|||
|
<span class="nx">modal</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">none</span><span class="dl">"</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="nt"></script></span>
|
|||
|
|
|||
|
<span class="nt"></body></span>
|
|||
|
<span class="nt"></html></span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="openldap-client">OpenLDAP Client</h2>
|
|||
|
|
|||
|
<h3 id="configuration-du-client">Configuration du client</h3>
|
|||
|
|
|||
|
<p><strong>Machine debian stretch sur virtualbox/PC1</strong><br />
|
|||
|
machine : dbs</p>
|
|||
|
|
|||
|
<p>Accès ssh</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh dbsuser@192.168.0.47 -p 22 -i /home/yannick/.ssh/vbox-dbs-ed25519
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>Raccorder le client au serveur LDAP et vérifier la consultation de l’annuaire</li>
|
|||
|
<li>Installer la partie cliente pour augmenter la base des comptes locaux avec celle contenue dans la base LDAP</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<h4 id="raccordement-au-ldap">Raccordement au ldap</h4>
|
|||
|
|
|||
|
<p><strong>Toutes les commandes en mode su ou sudo</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installer les outils ldap</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install ldap-utils
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier la connexion au port SSL 636 du serveur</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>openssl s_client -connect ldap.cinay.eu:636 -showcerts
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CONNECTED(00000003)
|
|||
|
depth=0 C = FR, ST = Pays de Loire, L = SMM, O = home, CN = ldap.cinay.eu
|
|||
|
verify error:num=18:self signed certificate
|
|||
|
verify return:1
|
|||
|
depth=0 C = FR, ST = Pays de Loire, L = SMM, O = home, CN = ldap.cinay.eu
|
|||
|
verify return:1
|
|||
|
---
|
|||
|
Certificate chain
|
|||
|
0 s:C = FR, ST = Pays de Loire, L = SMM, O = home, CN = ldap.cinay.eu
|
|||
|
i:C = FR, ST = Pays de Loire, L = SMM, O = home, CN = ldap.cinay.eu
|
|||
|
-----BEGIN CERTIFICATE-----
|
|||
|
MIIFlTCCA32gAwIBAgIUeXV2oJaFi7zIHu7AZGAwqFbPOm8wDQYJKoZIhvcNAQEL
|
|||
|
[...]
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Création du dossier ssl</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir /etc/ldap/ssl
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Récupérer le certificat <strong>cert.pem</strong> du serveur pour que le client puisse valider qu’il s’adresse au bon endroit.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat > /etc/ldap/ssl/cert.pem
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Copier/coller le contenu du fichier <strong>cert.pem</strong> du serveur <strong>ldap.cinay.eu</strong> dans ce terminal, et presser [Ctrl]+[D] pour valider.</p>
|
|||
|
|
|||
|
<p>Configurer le fichier <strong>/etc/ldap/ldap.conf</strong> pour y insérer les informations de connexion au serveur LDAP</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#
|
|||
|
# LDAP Defaults
|
|||
|
#
|
|||
|
|
|||
|
# See ldap.conf(5) for details
|
|||
|
# This file should be world readable but not world writable.
|
|||
|
|
|||
|
BASE dc=ldap,dc=cinay,dc=eu
|
|||
|
URI ldaps://ldap.cinay.eu
|
|||
|
|
|||
|
# TLS certificates (needed for GnuTLS)
|
|||
|
TLS_CACERT /etc/ldap/ssl/cert.pem
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Les paramètres</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><strong>BASE</strong> → synonyme de l’option <strong>-b</strong> des commandes clientes ldap</li>
|
|||
|
<li><strong>URI</strong> → synonyme de l’option <strong>-H</strong></li>
|
|||
|
<li><strong>TLS_CACERT</strong> → Emplacement du certificat</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Test depuis le client</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapsearch -x
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># extended LDIF
|
|||
|
#
|
|||
|
# LDAPv3
|
|||
|
# base <dc=ldap,dc=cinay,dc=eu> (default) with scope subtree
|
|||
|
# filter: (objectclass=*)
|
|||
|
# requesting: ALL
|
|||
|
#
|
|||
|
|
|||
|
# ldap.cinay.eu
|
|||
|
dn: dc=ldap,dc=cinay,dc=eu
|
|||
|
objectClass: top
|
|||
|
objectClass: dcObject
|
|||
|
objectClass: organization
|
|||
|
o: ldap.cinay.eu
|
|||
|
dc: ldap
|
|||
|
|
|||
|
# admin, ldap.cinay.eu
|
|||
|
dn: cn=admin,dc=ldap,dc=cinay,dc=eu
|
|||
|
objectClass: simpleSecurityObject
|
|||
|
objectClass: organizationalRole
|
|||
|
cn: admin
|
|||
|
description: LDAP administrator
|
|||
|
|
|||
|
# posixaccounts, ldap.cinay.eu
|
|||
|
dn: ou=posixaccounts,dc=ldap,dc=cinay,dc=eu
|
|||
|
objectClass: organizationalUnit
|
|||
|
ou: posixaccounts
|
|||
|
|
|||
|
# posixgroups, ldap.cinay.eu
|
|||
|
dn: ou=posixgroups,dc=ldap,dc=cinay,dc=eu
|
|||
|
objectClass: organizationalUnit
|
|||
|
ou: posixgroups
|
|||
|
|
|||
|
# yanspm, posixaccounts, ldap.cinay.eu
|
|||
|
dn: uid=yanspm,ou=posixaccounts,dc=ldap,dc=cinay,dc=eu
|
|||
|
uid: yanspm
|
|||
|
sn: yanspm
|
|||
|
homeDirectory: /home/yanspm
|
|||
|
cn: yanspm
|
|||
|
objectClass: inetOrgPerson
|
|||
|
objectClass: posixAccount
|
|||
|
objectClass: top
|
|||
|
loginShell: /bin/bash
|
|||
|
uidNumber: 6001
|
|||
|
gidNumber: 6001
|
|||
|
gecos: yan
|
|||
|
mail: yanspm@cinay.xyz
|
|||
|
|
|||
|
# yanspm, posixgroups, ldap.cinay.eu
|
|||
|
dn: cn=yanspm,ou=posixgroups,dc=ldap,dc=cinay,dc=eu
|
|||
|
objectClass: posixGroup
|
|||
|
objectClass: top
|
|||
|
gidNumber: 6001
|
|||
|
cn: yanspm
|
|||
|
|
|||
|
# search result
|
|||
|
search: 2
|
|||
|
result: 0 Success
|
|||
|
|
|||
|
# numResponses: 7
|
|||
|
# numEntries: 6
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>La commande renvoie les 6 entrées de l’annuaire:<br />
|
|||
|
racine + 2 OU + admin de la racine + compte + groupe</p>
|
|||
|
|
|||
|
<h3 id="complétion-des-comptes-locaux-avec-ldap">Complétion des comptes locaux avec LDAP</h3>
|
|||
|
|
|||
|
<p>Le programme NSS (Name Switching Service) gère les bases de compte Linux.<br />
|
|||
|
Il s’appuie sur le service SSSD (System Security Service Daemon) qui pointe sur le serveur LDAP<br />
|
|||
|
SSSD présente à NSS les comptes stockés dans LDAP</p>
|
|||
|
|
|||
|
<p>En premier , installer SSSD</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install sssd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Suite à cette installation , vue sur le fichier de configuration NSS</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat /etc/nsswitch.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># /etc/nsswitch.conf
|
|||
|
#
|
|||
|
# Example configuration of GNU Name Service Switch functionality.
|
|||
|
# If you have the `glibc-doc-reference' and `info' packages installed, try:
|
|||
|
# `info libc "Name Service Switch"' for information about this file.
|
|||
|
|
|||
|
passwd: compat sss
|
|||
|
group: compat sss
|
|||
|
shadow: compat sss
|
|||
|
[...]
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>On voit que le programme NSS va interroger le service SSSD (sss), cela concerne les bases <em>passwd</em> , <em>group</em> et <em>shadow</em></p>
|
|||
|
|
|||
|
<p>Configurer le service SSSD avec les information de notre serveur LDAP avec le fichier <strong>/etc/sssd/sssd.conf</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/sssd/sssd.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[sssd]
|
|||
|
services = nss, pam
|
|||
|
domains = LOCAL, LDAP
|
|||
|
|
|||
|
[domain/LDAP]
|
|||
|
description = LOCAL Users domain
|
|||
|
id_provider = local
|
|||
|
enumerate = True
|
|||
|
|
|||
|
[domain/LDAP]
|
|||
|
id_provider = ldap
|
|||
|
auth_provider = ldap
|
|||
|
ldap_schema = rfc2307
|
|||
|
ldap_uri = ldaps://ldap.cinay.eu
|
|||
|
ldap_search_base = dc=ldap,dc=cinay,dc=eu
|
|||
|
enumerate = True
|
|||
|
ldap_tls_cacert = /etc/ldap/ssl/cert.pem
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>La ligne <strong>services</strong> nous informe que SSSD sera utilisé pour la gestion des comptes (<em>nss</em>) et l’authentification (<em>pam</em>)</li>
|
|||
|
<li>La ligne <strong>domains</strong> prend 2 valeurs :
|
|||
|
<ul>
|
|||
|
<li><strong>LOCAL</strong> correspond aux comptes locaux de la machine (<strong>/etc/passwd,/etc/group et/etc/shadow</strong>)</li>
|
|||
|
<li><strong>LDAP</strong> corresopn aux comptes stockés dans LDAP</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li>Section <strong>[domain/LDAP]</strong> : Nous retrouvons les paramètres de configuration du <strong>ldap.conf</strong> , la spécification du protocole LDAP comme méthode d’accès au compte (<strong>id_provider</strong>) et “credentials” d’authentification (<strong>auth_provider</strong>)</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Relancer le service (il est validé lors de l’installation)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart sssd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérification</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>getent passwd |grep "yanspm"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yanspm:*:6001:6001:yan:/home/yanspm:/bin/bash
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>La commande <code class="language-plaintext highlighter-rouge">getent</code> prend comme paramètre une base NSS (passwd,group ou shadow) et en affiche le contenu<br />
|
|||
|
Nous affichons la base <em>passwd</em> qui contient bien le compte LDAP yanspm</p>
|
|||
|
|
|||
|
<p>Créer un <strong>home</strong> pour l’utilisateur <em>yanspm</em></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir /home/yanspm
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Les droits</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chown yanspm:yanspm /home/yanspm
|
|||
|
chmod 750 /home/yanspm
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>On se déconnecte du client</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>logout
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>On s’authentifie avec l’utilisateur <em>yanspm</em> créer dans LDAP et on vérifie</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>id
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yanspm:*:6001:6001:yan:/home/yanspm:/bin/bash
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h1 id="annuaire-ldap-debian-buster">Annuaire LDAP Debian Buster</h1>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><a href="/2019/10/05/OpenLDAP-installation-configuration-annuaire.html">OpenLDAP installation et configuration annuaire</a></li>
|
|||
|
<li><a href="https://computingforgeeks.com/how-to-install-and-configure-openldap-server-on-debian/">How To Install and Configure OpenLDAP Server on Debian 10 (Buster)</a></li>
|
|||
|
<li><a href="https://computingforgeeks.com/how-to-configure-ubuntu-18-04-ubuntu-16-04-lts-as-ldap-client/">How to configure LDAP Client</a></li>
|
|||
|
<li><a href="https://computingforgeeks.com/secure-ldap-server-with-ssl-tls-on-ubuntu/">Secure LDAP Server with SSL/TLS</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Avant de commencer l’installation, configurez le nom d’hôte FQDN de votre serveur et ajoutez un enregistrement au fichier <strong>/etc/hosts</strong><br />
|
|||
|
Relever l’adresse ip de votre serveur <code class="language-plaintext highlighter-rouge">ip a</code> (ici notre adresse ip 192.168.0.45)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "192.168.0.45 ldap.xoyize.xyz" | sudo tee -a /etc/hosts
|
|||
|
sudo hostnamectl set-hostname ldap.xoyize.xyz --static
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="installation--configuration-et-tests-openldap">Installation , configuration et tests openLDAP</h3>
|
|||
|
|
|||
|
<p><strong>Installation et configuration</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>DEBIAN_FRONTEND=noninteractive apt-get -yq install slapd ldap-utils net-tools
|
|||
|
dpkg-reconfigure slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Voulez-vous omettre la configuration d’OpenLDAP ? Non
|
|||
|
Nom de domaine : xoyize.xyz
|
|||
|
Nom d’entité (« organization ») : xoyize.xyz
|
|||
|
Mot de passe de l’administrateur : *******
|
|||
|
Module de base de données à utiliser : MDB
|
|||
|
Faut-il supprimer la base de données lors de la purge du paquet ? Non
|
|||
|
Faut-il déplacer l’ancienne base de données ? Oui
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>ATTENTION ATTENTION ATTENTION</strong><br />
|
|||
|
DEBIAN 10 (Buster) avec la saisie nom de domaine ldap.xoyize.xyz donnera dc=xoyize,dc=xyz , la base LDAP sera ERRONEE <br />
|
|||
|
DEBIAN 9 (Stretch) avec la saisie nom de domaine ldap.xoyize.xyz donnera dc=ldap,dc=xoyize,dc=xyz</p>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>Dans la saisie <strong>Nom de domaine + entité</strong> , NE PAS METTRE <strong>ldap.</strong> ,SEULEMENT <strong>xoyize.xyz</strong></p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p><strong>Tests</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl enable slapd # activation
|
|||
|
systemctl start slapd # exécution
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ecoute</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>netstat -laputn | grep slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tcp 0 0 0.0.0.0:389 0.0.0.0:* LISTEN 10204/slapd
|
|||
|
tcp6 0 0 :::389 :::* LISTEN 10204/slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Avec quels arguments s’exécute le service.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat /var/run/slapd/slapd.args
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/usr/sbin/slapd -h ldap:/// ldapi:/// -g openldap -u openldap -F /etc/ldap/slapd.d
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>-h</strong> → les modalités d’accès à slapd : ldap et ldapi (ldap via TCP 389 et ldapi via socket unix)<br />
|
|||
|
<strong>-g</strong> et <strong>-u</strong> → identité groupe et utilisateur sur lequel “tourne” le processus slapd<br />
|
|||
|
<strong>-F</strong> → emplacement du ficher de configuration de slapd</p>
|
|||
|
|
|||
|
<p>Afficher les données de l’annuaire</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapsearch -x -H ldap://ldap.xoyize.xyz -b 'dc=xoyize,dc=xyz'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># extended LDIF
|
|||
|
#
|
|||
|
# LDAPv3
|
|||
|
# base <dc=xoyize,dc=xyz> with scope subtree
|
|||
|
# filter: (objectclass=*)
|
|||
|
# requesting: ALL
|
|||
|
#
|
|||
|
|
|||
|
# search result
|
|||
|
search: 2
|
|||
|
result: 32 No such object
|
|||
|
matchedDN: dc=xoyize,dc=xyz
|
|||
|
|
|||
|
# numResponses: 1
|
|||
|
root@ldap:/home/admbust# ldapsearch -x -H ldap://ldap.xoyize.xyz -b 'dc=xoyize,dc=xyz'
|
|||
|
# extended LDIF
|
|||
|
#
|
|||
|
# LDAPv3
|
|||
|
# base <dc=xoyize,dc=xyz> with scope subtree
|
|||
|
# filter: (objectclass=*)
|
|||
|
# requesting: ALL
|
|||
|
#
|
|||
|
|
|||
|
# xoyize.xyz
|
|||
|
dn: dc=xoyize,dc=xyz
|
|||
|
objectClass: top
|
|||
|
objectClass: dcObject
|
|||
|
objectClass: organization
|
|||
|
o: xoyize.xyz
|
|||
|
dc: xoyize
|
|||
|
|
|||
|
# admin, xoyize.xyz
|
|||
|
dn: cn=admin,dc=xoyize,dc=xyz
|
|||
|
objectClass: simpleSecurityObject
|
|||
|
objectClass: organizationalRole
|
|||
|
cn: admin
|
|||
|
description: LDAP administrator
|
|||
|
|
|||
|
# search result
|
|||
|
search: 2
|
|||
|
result: 0 Success
|
|||
|
|
|||
|
# numResponses: 3
|
|||
|
# numEntries: 2
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="peuplement-de-lannuaire-1">Peuplement de l’annuaire</h3>
|
|||
|
|
|||
|
<p>Peupler l’annuaire en créant les deux <strong>OU</strong> puis un compte système avec son groupe primaire.<br />
|
|||
|
Créer un fichier au format LDIF (LDAP Data Interchange Format)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat > ou.ldif << EOF
|
|||
|
dn: ou=posixaccounts,dc=xoyize,dc=xyz
|
|||
|
objectclass: OrganizationalUnit
|
|||
|
|
|||
|
dn: ou=posixgroups,dc=xoyize,dc=xyz
|
|||
|
objectclass: OrganizationalUnit
|
|||
|
|
|||
|
EOF
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ajouter à l’annuaire (mot de passe admin)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapadd -x -H ldap://ldap.xoyize.xyz -D 'cn=admin,dc=xoyize,dc=xyz' -f ou.ldif -W
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ajouter le compte (utilisateur mot de passe) avec le groupe primaire<br />
|
|||
|
Pour créer l’empreinte du mot de passe ,utiliser <code class="language-plaintext highlighter-rouge">slappasswd</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat > userandupg.ldif << EOF
|
|||
|
dn: uid=yannick, ou=posixaccounts,dc=xoyize,dc=xyz
|
|||
|
uid: yannick
|
|||
|
sn: yannick
|
|||
|
homeDirectory: /home/yannick
|
|||
|
cn: yannick
|
|||
|
objectClass: inetOrgPerson
|
|||
|
objectClass: posixAccount
|
|||
|
objectClass: top
|
|||
|
loginShell: /bin/bash
|
|||
|
uidNumber: 6001
|
|||
|
gidNumber: 6001
|
|||
|
gecos: yan
|
|||
|
mail: yannick@cinay.xyz
|
|||
|
userPassword: {SSHA}NGdnkYoutO+bSUVDV1X+H6WvBBi4Cv17
|
|||
|
|
|||
|
dn: cn=yannick,ou=posixgroups,dc=xoyize,dc=xyz
|
|||
|
objectClass: posixGroup
|
|||
|
objectClass: top
|
|||
|
gidNumber: 6001
|
|||
|
cn: yannick
|
|||
|
|
|||
|
EOF
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ajout des 2 objets</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapadd -x -H ldap://ldap.xoyize.xyz -D 'cn=admin,dc=xoyize,dc=xyz' -f userandupg.ldif -W
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Supprimer les .ldif</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rm *.ldif
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="sécurisation-ssl">Sécurisation SSL</h3>
|
|||
|
|
|||
|
<p>SSL, couche additionnelle à TCP qui chiffre les échanges.<br />
|
|||
|
On va activer ldaps et modifier les paramètres de lancement du service et générer un certificat.</p>
|
|||
|
|
|||
|
<p><strong>Création des certificats</strong><br />
|
|||
|
Création du répertoire ssl et génération certificat autosigné (validité 10ans)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p /etc/ldap/ssl && cd /etc/ldap/ssl
|
|||
|
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 3650 -nodes
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le champ <strong>Common Name</strong> est le plus important</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Common Name (e.g. server FQDN or YOUR name) []:ldap.xoyize.xyz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Changer les permissions sur les 2 fichiers (utilisateur <em>openldap</em>) , clé privée accessible par root uniquement</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chown openldap:openldap /etc/ldap/ssl/key.pem
|
|||
|
chown openldap:openldap /etc/ldap/ssl/cert.pem
|
|||
|
chmod 400 /etc/ldap/ssl/key.pem
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Configuration de slapd</strong><br />
|
|||
|
Ajout de 2 directives pour trouver le couple clé/certificat</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat > cert.ldif << EOF
|
|||
|
dn: cn=config
|
|||
|
changetype: modify
|
|||
|
replace: olcTLSCACertificateFile
|
|||
|
olcTLSCACertificateFile: /etc/ldap/ssl/cert.pem
|
|||
|
-
|
|||
|
replace: olcTLSCertificateFile
|
|||
|
olcTLSCertificateFile: /etc/ldap/ssl/cert.pem
|
|||
|
-
|
|||
|
replace: olcTLSCertificateKeyFile
|
|||
|
olcTLSCertificateKeyFile: /etc/ldap/ssl/key.pem
|
|||
|
|
|||
|
EOF
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Pour appliquer les modifications ,nous allons passer par le mode ldapi car il n’y a pas de compte administrateur associé à la racine cn=config</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapmodify -Y EXTERNAL -H ldapi:/// -f cert.ldif # pas de mot de passe
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SASL/EXTERNAL authentication started
|
|||
|
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
|
|||
|
SASL SSF: 0
|
|||
|
create: 2019-10-05
|
|||
|
modifying entry "cn=config"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>create: 2019-10-05
|
|||
|
modifier le fichier <strong>/etc/default/slapd</strong> pour lui indiquer qu’il doit gérer la méthode d’accès ldaps</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/default/slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SLAPD_SERVICES="ldap:/// ldapi:/// ldaps:///"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Relancer slapd et vérifier</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart slapd && netstat -laputn | grep slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tcp 0 0 0.0.0.0:636 0.0.0.0:* LISTEN 10678/slapd
|
|||
|
tcp 0 0 0.0.0.0:389 0.0.0.0:* LISTEN 10678/slapd
|
|||
|
tcp6 0 0 :::636 :::* LISTEN 10678/slapd
|
|||
|
tcp6 0 0 :::389 :::* LISTEN 10678/slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le service slapd est en écoute SSL sur le port 636</p>
|
|||
|
|
|||
|
<h3 id="modifier-le-mot-de-passe-admin">Modifier le mot de passe admin</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapsearch -LLLL -Y EXTERNAL -H ldapi://// -b cn=config olcRootDN=cn=admin,dc=xoyize,dc=xyz dn olcRootDN oulcRootPW
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SASL/EXTERNAL authentication started
|
|||
|
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
|
|||
|
SASL SSF: 0
|
|||
|
dn: olcDatabase={1}mdb,cn=config
|
|||
|
olcRootDN: cn=admin,dc=xoyize,dc=xyz
|
|||
|
olcRootPW: {SSHA}5HDG17qV4Z6/YaLCCnrM5YTt3kFxgEAB
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Il y a deux informations intéressantes que nous connaissons maintenant :</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>il faut modifier l’entrée “dn: olcDatabase={1}mdb,cn=config”.</li>
|
|||
|
<li>le mot de passe courant est haché avec SSHA algorythm.</li>
|
|||
|
<li>Nous devons donc générer notre nouveau mot de passe avec la même algorythme en utilisant la commande slappasswd en utilisant la syntaxe</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p><code class="language-plaintext highlighter-rouge">slappasswd -h <the hashing scheme we want to use - for example {SHA}></code></p>
|
|||
|
|
|||
|
<p>Le système nous demandera alors deux fois le nouveau mot de passe à utiliser et affichera finalement la valeur de hachage qui nous intéresse (exemple ci-dessous avec mot de passe = mot de passe).</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>slappasswd -h {SSHA} New password
|
|||
|
Re-enter new password:
|
|||
|
{SSHA}3BtYMALVeaFu44ZYLEjK7k4Pj
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ensuite, nous allons procéder à la modification de l’entrée que nous avons identifiée ci-dessus à l’aide de la commande :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapmodify -Y EXTERNAL -H ldapi:///
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le système démarre le mode d’écoute pour modifier les commandes :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SASL/EXTERNAL authentication started
|
|||
|
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
|
|||
|
SASL SSF: 0
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Tout d’abord, nous entrons l’entrée que nous voulons modifier :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dn : olcDatabase={1}mdb,cn=config
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ensuite, nous tapons le paramètre que nous voulons modifier :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>remplacer : olcRootPW
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Troisièmement, nous tapons le nouveau mot de passe généré ci-dessus (copier-coller est BEAUCOUP moins sujet aux erreurs que la saisie manuelle à ce point)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>olcRootPW : {SSHA}3BtYMALVeaFu44ZYLEjK7k4Pj
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Appuyez sur Entrée une autre fois pour valider la modification et la ligne suivante apparaîtra :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>modification de l'entrée "olcDatabase={1}mdb,cn=config".
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ensuite, vous pouvez quitter le mode d’écoute avec CTRL+C et redémarrer le service de base de données LDAP avec</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart slapd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et connectez-vous maintenant avec le nouveau mot de passe défini.</p>
|
|||
|
|
|||
|
<h3 id="openldap-php-sur-serveur-1">OpenLDAP PHP sur serveur</h3>
|
|||
|
|
|||
|
<p>Installer le module</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install php7.3-ldap
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Fichiers de test <strong>/var/www/default-www/test.php</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /var/www/default-www/test.php
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?php
|
|||
|
$baseDN = "dc=xoyize,dc=xyz";
|
|||
|
$ldapServer = "ldap.xoyize.xyz";
|
|||
|
$ldapServerPort = 389;
|
|||
|
$dn = 'cn=admin,dc=xoyize,dc=xyz';
|
|||
|
|
|||
|
echo "Connexion au serveur <br />";
|
|||
|
$conn=ldap_connect($ldapServer);
|
|||
|
|
|||
|
// on teste : le serveur LDAP est-il trouvé ?
|
|||
|
if ($conn) {
|
|||
|
echo "Le résultat de connexion est ".$conn ."<br />";
|
|||
|
} else {
|
|||
|
die("connexion impossible au serveur LDAP");
|
|||
|
}
|
|||
|
|
|||
|
// 2ème étape : on effectue une liaison au serveur, ici de type "anonyme"
|
|||
|
// pour une recherche permise par un accès en lecture seule
|
|||
|
|
|||
|
// On dit qu'on utilise LDAP V3, sinon la V2 par défaut est utilisé
|
|||
|
// et le bind ne passe pas.
|
|||
|
if (ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3)) {
|
|||
|
echo "Utilisation de LDAPv3 <br />";
|
|||
|
} else {
|
|||
|
echo "Impossible d'utiliser LDAP V3<br />";
|
|||
|
exit;
|
|||
|
}
|
|||
|
|
|||
|
// Instruction de liaison.
|
|||
|
// Connexion anonyme
|
|||
|
print ("Connexion anonyme...<br />");
|
|||
|
$bindServerLDAP=ldap_bind($conn);
|
|||
|
|
|||
|
echo "Liaison au serveur : ". ldap_error($conn)."<br />";
|
|||
|
// en cas de succès de la liaison, renvoie Vrai
|
|||
|
if ($bindServerLDAP)
|
|||
|
echo "Le résultat de connexion est $bindServerLDAP <br />";
|
|||
|
else
|
|||
|
die("Liaison impossible au serveur ldap ...");
|
|||
|
|
|||
|
/* 3ème étape : on effectue une recherche anonyme, avec le dn de base,
|
|||
|
* par exemple, sur tous les noms commençant par B
|
|||
|
*/
|
|||
|
echo "Recherche suivant le filtre (sn=y*) <br />";
|
|||
|
$query = "sn=y*";
|
|||
|
$result=ldap_search($conn, $baseDN, $query);
|
|||
|
echo "Le résultat de la recherche est $result <br />";
|
|||
|
|
|||
|
echo "Le nombre d'entrées retournées est ".ldap_count_entries($conn,$result)."<p />";
|
|||
|
echo "Lecture de ces entrées ....<p />";
|
|||
|
$info = ldap_get_entries($conn, $result);
|
|||
|
echo "Données pour ".$info["count"]." entrées:<p />";
|
|||
|
|
|||
|
for ($i=0; $i < $info["count"]; $i++) {
|
|||
|
echo "dn est : ". $info[$i]["cn"] ."<br />";
|
|||
|
echo "premiere entree cn : ". $info[$i]["cn"][0] ."<br />";
|
|||
|
echo "premier email : ". $info[$i]["mail"][0] ."<p />";
|
|||
|
}
|
|||
|
|
|||
|
// Test utilisateur mot de passe
|
|||
|
if($bindServerLDAP = @ldap_bind($conn, "uid=yannick,ou=posixaccounts,dc=xoyize,dc=xyz", "khtus44sf46")) {
|
|||
|
echo "OK Test utilisateur mot de passe <br />";
|
|||
|
} else {
|
|||
|
echo "ERROR Test utilisateur mot de passe <br />";
|
|||
|
}
|
|||
|
|
|||
|
echo "Fermeture de la connexion";
|
|||
|
ldap_close($conn);
|
|||
|
?>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Attribut fichier</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo chown $USER:www-data /var/www/default-www/test.php
|
|||
|
chmod +x /var/www/default-www/test.php
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Test sur le lien https://xoyize.xyz/test.php</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Connexion au serveur
|
|||
|
Le résultat de connexion est Resource id #2
|
|||
|
Utilisation de LDAPv3
|
|||
|
Connexion anonyme...
|
|||
|
Liaison au serveur : Success
|
|||
|
Le résultat de connexion est 1
|
|||
|
Recherche suivant le filtre (sn=y*)
|
|||
|
Le résultat de la recherche est Resource id #3
|
|||
|
Le nombre d'entrées retournées est 1
|
|||
|
|
|||
|
Lecture de ces entrées ....
|
|||
|
|
|||
|
Données pour 1 entrées:
|
|||
|
|
|||
|
dn est : Array
|
|||
|
premiere entree cn : yannick
|
|||
|
premier email : yannick@cinay.xyz
|
|||
|
|
|||
|
OK Test utilisateur mot de passe
|
|||
|
Fermeture de la connexion
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Une fois la vérification effectuée , supprimer le fichier <strong>test.php</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo rm /var/www/default-www/test.php
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="phpldapadmin">PhpLdapAdmin</h2>
|
|||
|
|
|||
|
<h3 id="pré-requis">Pré-requis</h3>
|
|||
|
|
|||
|
<p>Pour pouvoir utiliser phpLDAPadmin, vous aurez besoin des éléments suivants :</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Un serveur LDAP en cours d’exécution de votre choix, quelque part dans votre réseau.
|
|||
|
phpLDAPadmin a été développé pour gérer un serveur OpenLDAP, mais il devrait également fonctionner avec d’autres serveurs LDAP. Si vous rencontrez des problèmes avec PLA et votre serveur LDAP, contactez les développeurs et ils se feront un plaisir d’apporter les modifications nécessaires pour que cela fonctionne.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Votre serveur LDAP doit également fournir l’accès au schéma en utilisant un lien anonyme. Veuillez vous assurer que vous pouvez voir votre schéma sans avoir à vous lier au serveur LDAP. Un moyen de tester cela pourrait être aussi simple que :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapsearch -xh HOST -b ''' -s base subschemaSubentry
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Un serveur web (Nginx, Apache, IIS, etc.).</li>
|
|||
|
<li>Votre serveur web configuré pour utiliser PHP v5 ou + . PHP doit être configuré avec :
|
|||
|
<ul>
|
|||
|
<li>Support PCRE</li>
|
|||
|
<li>Prise en charge des SESSION</li>
|
|||
|
<li>Support GETTEXT</li>
|
|||
|
<li>Support LDAP</li>
|
|||
|
<li>Support XML</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3 id="installation-1">Installation</h3>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>Installez et configurez votre serveur LDAP favori quelque part sur votre réseau. (Ou, obtenez vos détails LDAP auprès de votre administrateur LDAP.)</li>
|
|||
|
<li>Assurez-vous d’avoir toutes les conditions préalables requises</li>
|
|||
|
<li>git phpldapadmin version 1.25</li>
|
|||
|
<li>Décompressez l’archive à un endroit pratique.</li>
|
|||
|
<li>Placez le répertoire’phpldapadmin’ résultant quelque part dans votre webroot.</li>
|
|||
|
<li>Copiez’config.php.example’ dans’config.php’ et éditez selon votre goût. <br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo cp /var/www/phpldapadmin/config/config.php.example /var/www/phpldapadmin/config/config.php</code></li>
|
|||
|
<li>Ensuite, pointez votre navigateur vers le répertoire phpldapadmin → https://lm.xoyize.xyz</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/leenooks/phpLDAPadmin.git
|
|||
|
sudo mv phpLDAPadmin /var/www/phpldapadmin
|
|||
|
sudo chown www-data:www-data -R /var/www/phpldapadmin/
|
|||
|
sudo cp /var/www/phpldapadmin/config/config.php.example /var/www/phpldapadmin/config/config.php
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="configuration-nginx">configuration nginx</h3>
|
|||
|
|
|||
|
<p>Fichier de configuration nginx <strong>/etc/nginx/conf.d/lm.xoyize.xyz.conf</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/nginx/conf.d/lm.xoyize.xyz.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
|
|||
|
listen 80;
|
|||
|
listen [::]:80;
|
|||
|
|
|||
|
## redirect http to https ##
|
|||
|
server_name lm.xoyize.xyz;
|
|||
|
return 301 https://$server_name$request_uri;
|
|||
|
}
|
|||
|
|
|||
|
server {
|
|||
|
listen 443 ssl http2;
|
|||
|
listen [::]:443 ssl http2;
|
|||
|
server_name lm.xoyize.xyz;
|
|||
|
|
|||
|
include ssl_params;
|
|||
|
include header_params;
|
|||
|
# Diffie-Hellmann
|
|||
|
# Uncomment the following directive after DH generation
|
|||
|
# > openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048
|
|||
|
# ssl_dhparam /etc/ssl/private/dh2048.pem;
|
|||
|
|
|||
|
root /var/www/phpldapadmin;
|
|||
|
index index.php;
|
|||
|
|
|||
|
location ~ \.php$ {
|
|||
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
|||
|
fastcgi_pass unix:/run/php/php7.3-fpm.sock; # PHP7.3
|
|||
|
fastcgi_index index.php;
|
|||
|
include fastcgi_params;
|
|||
|
fastcgi_param SCRIPT_FILENAME $request_filename;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
access_log /var/log/nginx/lm.xoyize.xyz-access.log;
|
|||
|
error_log /var/log/nginx/lm.xoyize.xyz-error.log;
|
|||
|
}
|
|||
|
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérification et rechargement nginx</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nginx -t
|
|||
|
sudo systemctl reload nginx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Accès https://lm.xoyize.xyz</p>
|
|||
|
|
|||
|
<p><img src="/images/phpldapadmin01.png" alt="" width="400" /></p>
|
|||
|
|
|||
|
<p>Accès par le lien https://lm.xoyize.xyz</p>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2019-10-05T00:00:00+02:00"><!-- start custom article footer snippet -->
|
|||
|
|
|||
|
<!-- end custom article footer snippet -->
|
|||
|
<!--
|
|||
|
<div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>
|
|||
|
|
|||
|
 </div>
|
|||
|
-->
|
|||
|
</footer>
|
|||
|
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2019/09/26/PHP-connexion-et-administration-annuaire-LDAP.html">PHP connexion et administration annuaire LDAP</a></div><div class="next"><span>SUIVANT</span><a href="/2019/10/08/Configuration_nginx_ssl_(tls1.2-tls1.3)_Diffie-Hellman_Headers_OCSP.html">Configuration nginx , ssl (tls1.2 tls1.3) , Diffie Hellman ,Headers et OCSP</a></div></div></div>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
<script>(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
$(function() {
|
|||
|
var $this ,$scroll;
|
|||
|
var $articleContent = $('.js-article-content');
|
|||
|
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
|
|||
|
var scroll = hasSidebar ? '.js-page-main' : 'html, body';
|
|||
|
$scroll = $(scroll);
|
|||
|
|
|||
|
$articleContent.find('.highlight').each(function() {
|
|||
|
$this = $(this);
|
|||
|
$this.attr('data-lang', $this.find('code').attr('data-lang'));
|
|||
|
});
|
|||
|
$articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
|
|||
|
$this = $(this);
|
|||
|
$this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
|
|||
|
});
|
|||
|
$articleContent.on('click', '.anchor', function() {
|
|||
|
$scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
})();
|
|||
|
</script>
|
|||
|
|
|||
|
</div><section class="page__comments d-print-none"></section></article><!-- start custom main bottom snippet -->
|
|||
|
<!-- end custom main bottom snippet -->
|
|||
|
</div>
|
|||
|
</div></div></div></div>
|
|||
|
</div><script>(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
var $body = $('body'), $window = $(window);
|
|||
|
var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
|
|||
|
var activeCount = 0;
|
|||
|
function modal(options) {
|
|||
|
var $root = this, visible, onChange, hideWhenWindowScroll = false;
|
|||
|
var scrollTop;
|
|||
|
function setOptions(options) {
|
|||
|
var _options = options || {};
|
|||
|
visible = _options.initialVisible === undefined ? false : show;
|
|||
|
onChange = _options.onChange;
|
|||
|
hideWhenWindowScroll = _options.hideWhenWindowScroll;
|
|||
|
}
|
|||
|
function init() {
|
|||
|
setState(visible);
|
|||
|
}
|
|||
|
function setState(isShow) {
|
|||
|
if (isShow === visible) {
|
|||
|
return;
|
|||
|
}
|
|||
|
visible = isShow;
|
|||
|
if (visible) {
|
|||
|
activeCount++;
|
|||
|
scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
|
|||
|
$root.addClass('modal--show');
|
|||
|
$pageMain.scrollTop(scrollTop);
|
|||
|
activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
|
|||
|
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
|
|||
|
$window.on('keyup', handleKeyup);
|
|||
|
} else {
|
|||
|
activeCount > 0 && activeCount--;
|
|||
|
$root.removeClass('modal--show');
|
|||
|
$window.scrollTop(scrollTop);
|
|||
|
activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
|
|||
|
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
|
|||
|
$window.off('keyup', handleKeyup);
|
|||
|
}
|
|||
|
onChange && onChange(visible);
|
|||
|
}
|
|||
|
function show() {
|
|||
|
setState(true);
|
|||
|
}
|
|||
|
function hide() {
|
|||
|
setState(false);
|
|||
|
}
|
|||
|
function handleKeyup(e) {
|
|||
|
// Char Code: 27 ESC
|
|||
|
if (e.which === 27) {
|
|||
|
hide();
|
|||
|
}
|
|||
|
}
|
|||
|
setOptions(options);
|
|||
|
init();
|
|||
|
return {
|
|||
|
show: show,
|
|||
|
hide: hide,
|
|||
|
$el: $root
|
|||
|
};
|
|||
|
}
|
|||
|
$.fn.modal = modal;
|
|||
|
});
|
|||
|
})();
|
|||
|
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
|
|||
|
(function () {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
// search panel
|
|||
|
var search = (window.search || (window.search = {}));
|
|||
|
var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
|
|||
|
true : window.useDefaultSearchBox ;
|
|||
|
|
|||
|
var $searchModal = $('.js-page-search-modal');
|
|||
|
var $searchToggle = $('.js-search-toggle');
|
|||
|
var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
|
|||
|
var modalVisible = false;
|
|||
|
search.searchModal = searchModal;
|
|||
|
|
|||
|
var $searchBox = null;
|
|||
|
var $searchInput = null;
|
|||
|
var $searchClear = null;
|
|||
|
|
|||
|
function getModalVisible() {
|
|||
|
return modalVisible;
|
|||
|
}
|
|||
|
search.getModalVisible = getModalVisible;
|
|||
|
|
|||
|
function handleModalChange(visible) {
|
|||
|
modalVisible = visible;
|
|||
|
if (visible) {
|
|||
|
search.onShow && search.onShow();
|
|||
|
useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
|
|||
|
} else {
|
|||
|
search.onShow && search.onHide();
|
|||
|
useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
|
|||
|
setTimeout(function() {
|
|||
|
useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
|
|||
|
search.clear && search.clear();
|
|||
|
window.pageAsideAffix && window.pageAsideAffix.refresh();
|
|||
|
}, 400);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
$searchToggle.on('click', function() {
|
|||
|
modalVisible ? searchModal.hide() : searchModal.show();
|
|||
|
});
|
|||
|
// Char Code: 83 S, 191 /
|
|||
|
$(window).on('keyup', function(e) {
|
|||
|
if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
|
|||
|
modalVisible || searchModal.show();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
if (useDefaultSearchBox) {
|
|||
|
$searchBox = $('.js-search-box');
|
|||
|
$searchInput = $searchBox.children('input');
|
|||
|
$searchClear = $searchBox.children('.js-icon-clear');
|
|||
|
search.getSearchInput = function() {
|
|||
|
return $searchInput.get(0);
|
|||
|
};
|
|||
|
search.getVal = function() {
|
|||
|
return $searchInput.val();
|
|||
|
};
|
|||
|
search.setVal = function(val) {
|
|||
|
$searchInput.val(val);
|
|||
|
};
|
|||
|
|
|||
|
$searchInput.on('focus', function() {
|
|||
|
$(this).addClass('focus');
|
|||
|
});
|
|||
|
$searchInput.on('blur', function() {
|
|||
|
$(this).removeClass('focus');
|
|||
|
});
|
|||
|
$searchInput.on('input', window.throttle(function() {
|
|||
|
var val = $(this).val();
|
|||
|
if (val === '' || typeof val !== 'string') {
|
|||
|
search.clear && search.clear();
|
|||
|
} else {
|
|||
|
$searchBox.addClass('not-empty');
|
|||
|
search.onInputNotEmpty && search.onInputNotEmpty(val);
|
|||
|
}
|
|||
|
}, 400));
|
|||
|
$searchClear.on('click', function() {
|
|||
|
$searchInput.val(''); $searchBox.removeClass('not-empty');
|
|||
|
search.clear && search.clear();
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
})();
|
|||
|
</script><div class="search search--dark">
|
|||
|
<div class="main">
|
|||
|
<div class="search__header">Recherche</div>
|
|||
|
<div class="search-bar">
|
|||
|
<div class="search-box js-search-box">
|
|||
|
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
|
|||
|
<input id="search-input" type="text" />
|
|||
|
<div class="search-box__icon-clear js-icon-clear">
|
|||
|
<a><i class="fas fa-times"></i></a>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<button class="button button--theme-dark button--pill search__cancel js-search-toggle">
|
|||
|
Annuler</button>
|
|||
|
</div>
|
|||
|
<div id="results-container" class="search-result js-search-result"></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<!-- Script pointing to search-script.js -->
|
|||
|
<script>/*!
|
|||
|
* Simple-Jekyll-Search
|
|||
|
* Copyright 2015-2020, Christian Fei
|
|||
|
* Licensed under the MIT License.
|
|||
|
*/
|
|||
|
|
|||
|
(function(){
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Templater_7 = {
|
|||
|
compile: compile,
|
|||
|
setOptions: setOptions
|
|||
|
}
|
|||
|
|
|||
|
const options = {}
|
|||
|
options.pattern = /\{(.*?)\}/g
|
|||
|
options.template = ''
|
|||
|
options.middleware = function () {}
|
|||
|
|
|||
|
function setOptions (_options) {
|
|||
|
options.pattern = _options.pattern || options.pattern
|
|||
|
options.template = _options.template || options.template
|
|||
|
if (typeof _options.middleware === 'function') {
|
|||
|
options.middleware = _options.middleware
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function compile (data) {
|
|||
|
return options.template.replace(options.pattern, function (match, prop) {
|
|||
|
const value = options.middleware(prop, data[prop], options.template)
|
|||
|
if (typeof value !== 'undefined') {
|
|||
|
return value
|
|||
|
}
|
|||
|
return data[prop] || match
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
'use strict';
|
|||
|
|
|||
|
function fuzzysearch (needle, haystack) {
|
|||
|
var tlen = haystack.length;
|
|||
|
var qlen = needle.length;
|
|||
|
if (qlen > tlen) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
if (qlen === tlen) {
|
|||
|
return needle === haystack;
|
|||
|
}
|
|||
|
outer: for (var i = 0, j = 0; i < qlen; i++) {
|
|||
|
var nch = needle.charCodeAt(i);
|
|||
|
while (j < tlen) {
|
|||
|
if (haystack.charCodeAt(j++) === nch) {
|
|||
|
continue outer;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
var _$fuzzysearch_1 = fuzzysearch;
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
|
|||
|
|
|||
|
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
|
|||
|
|
|||
|
function FuzzySearchStrategy () {
|
|||
|
this.matches = function (string, crit) {
|
|||
|
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
|
|||
|
|
|||
|
function LiteralSearchStrategy () {
|
|||
|
this.matches = function (str, crit) {
|
|||
|
if (!str) return false
|
|||
|
|
|||
|
str = str.trim().toLowerCase()
|
|||
|
crit = crit.trim().toLowerCase()
|
|||
|
|
|||
|
return crit.split(' ').filter(function (word) {
|
|||
|
return str.indexOf(word) >= 0
|
|||
|
}).length === crit.split(' ').length
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Repository_4 = {
|
|||
|
put: put,
|
|||
|
clear: clear,
|
|||
|
search: search,
|
|||
|
setOptions: __setOptions_4
|
|||
|
}
|
|||
|
|
|||
|
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
|
|||
|
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
|
|||
|
|
|||
|
function NoSort () {
|
|||
|
return 0
|
|||
|
}
|
|||
|
|
|||
|
const data = []
|
|||
|
let opt = {}
|
|||
|
|
|||
|
opt.fuzzy = false
|
|||
|
opt.limit = 10
|
|||
|
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = NoSort
|
|||
|
opt.exclude = []
|
|||
|
|
|||
|
function put (data) {
|
|||
|
if (isObject(data)) {
|
|||
|
return addObject(data)
|
|||
|
}
|
|||
|
if (isArray(data)) {
|
|||
|
return addArray(data)
|
|||
|
}
|
|||
|
return undefined
|
|||
|
}
|
|||
|
function clear () {
|
|||
|
data.length = 0
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function isObject (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
|
|||
|
}
|
|||
|
|
|||
|
function isArray (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
|
|||
|
}
|
|||
|
|
|||
|
function addObject (_data) {
|
|||
|
data.push(_data)
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function addArray (_data) {
|
|||
|
const added = []
|
|||
|
clear()
|
|||
|
for (let i = 0, len = _data.length; i < len; i++) {
|
|||
|
if (isObject(_data[i])) {
|
|||
|
added.push(addObject(_data[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
return added
|
|||
|
}
|
|||
|
|
|||
|
function search (crit) {
|
|||
|
if (!crit) {
|
|||
|
return []
|
|||
|
}
|
|||
|
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
|
|||
|
}
|
|||
|
|
|||
|
function __setOptions_4 (_opt) {
|
|||
|
opt = _opt || {}
|
|||
|
|
|||
|
opt.fuzzy = _opt.fuzzy || false
|
|||
|
opt.limit = _opt.limit || 10
|
|||
|
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = _opt.sort || NoSort
|
|||
|
opt.exclude = _opt.exclude || []
|
|||
|
}
|
|||
|
|
|||
|
function findMatches (data, crit, strategy, opt) {
|
|||
|
const matches = []
|
|||
|
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
|
|||
|
const match = findMatchesInObject(data[i], crit, strategy, opt)
|
|||
|
if (match) {
|
|||
|
matches.push(match)
|
|||
|
}
|
|||
|
}
|
|||
|
return matches
|
|||
|
}
|
|||
|
|
|||
|
function findMatchesInObject (obj, crit, strategy, opt) {
|
|||
|
for (const key in obj) {
|
|||
|
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
|
|||
|
return obj
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isExcluded (term, excludedTerms) {
|
|||
|
for (let i = 0, len = excludedTerms.length; i < len; i++) {
|
|||
|
const excludedTerm = excludedTerms[i]
|
|||
|
if (new RegExp(excludedTerm).test(term)) {
|
|||
|
return true
|
|||
|
}
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
/* globals ActiveXObject:false */
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$JSONLoader_2 = {
|
|||
|
load: load
|
|||
|
}
|
|||
|
|
|||
|
function load (location, callback) {
|
|||
|
const xhr = getXHR()
|
|||
|
xhr.open('GET', location, true)
|
|||
|
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
|
|||
|
xhr.send()
|
|||
|
}
|
|||
|
|
|||
|
function createStateChangeListener (xhr, callback) {
|
|||
|
return function () {
|
|||
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
|||
|
try {
|
|||
|
callback(null, JSON.parse(xhr.responseText))
|
|||
|
} catch (err) {
|
|||
|
callback(err, null)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function getXHR () {
|
|||
|
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$OptionsValidator_3 = function OptionsValidator (params) {
|
|||
|
if (!validateParams(params)) {
|
|||
|
throw new Error('-- OptionsValidator: required options missing')
|
|||
|
}
|
|||
|
|
|||
|
if (!(this instanceof OptionsValidator)) {
|
|||
|
return new OptionsValidator(params)
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = params.required
|
|||
|
|
|||
|
this.getRequiredOptions = function () {
|
|||
|
return requiredOptions
|
|||
|
}
|
|||
|
|
|||
|
this.validate = function (parameters) {
|
|||
|
const errors = []
|
|||
|
requiredOptions.forEach(function (requiredOptionName) {
|
|||
|
if (typeof parameters[requiredOptionName] === 'undefined') {
|
|||
|
errors.push(requiredOptionName)
|
|||
|
}
|
|||
|
})
|
|||
|
return errors
|
|||
|
}
|
|||
|
|
|||
|
function validateParams (params) {
|
|||
|
if (!params) {
|
|||
|
return false
|
|||
|
}
|
|||
|
return typeof params.required !== 'undefined' && params.required instanceof Array
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$utils_9 = {
|
|||
|
merge: merge,
|
|||
|
isJSON: isJSON
|
|||
|
}
|
|||
|
|
|||
|
function merge (defaultParams, mergeParams) {
|
|||
|
const mergedOptions = {}
|
|||
|
for (const option in defaultParams) {
|
|||
|
mergedOptions[option] = defaultParams[option]
|
|||
|
if (typeof mergeParams[option] !== 'undefined') {
|
|||
|
mergedOptions[option] = mergeParams[option]
|
|||
|
}
|
|||
|
}
|
|||
|
return mergedOptions
|
|||
|
}
|
|||
|
|
|||
|
function isJSON (json) {
|
|||
|
try {
|
|||
|
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
} catch (err) {
|
|||
|
return false
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var _$src_8 = {};
|
|||
|
(function (window) {
|
|||
|
'use strict'
|
|||
|
|
|||
|
let options = {
|
|||
|
searchInput: null,
|
|||
|
resultsContainer: null,
|
|||
|
json: [],
|
|||
|
success: Function.prototype,
|
|||
|
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
|
|||
|
templateMiddleware: Function.prototype,
|
|||
|
sortMiddleware: function () {
|
|||
|
return 0
|
|||
|
},
|
|||
|
noResultsText: 'No results found',
|
|||
|
limit: 10,
|
|||
|
fuzzy: false,
|
|||
|
debounceTime: null,
|
|||
|
exclude: []
|
|||
|
}
|
|||
|
|
|||
|
let debounceTimerHandle
|
|||
|
const debounce = function (func, delayMillis) {
|
|||
|
if (delayMillis) {
|
|||
|
clearTimeout(debounceTimerHandle)
|
|||
|
debounceTimerHandle = setTimeout(func, delayMillis)
|
|||
|
} else {
|
|||
|
func.call()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
|
|||
|
|
|||
|
/* removed: const _$Templater_7 = require('./Templater') */;
|
|||
|
/* removed: const _$Repository_4 = require('./Repository') */;
|
|||
|
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
|
|||
|
const optionsValidator = _$OptionsValidator_3({
|
|||
|
required: requiredOptions
|
|||
|
})
|
|||
|
/* removed: const _$utils_9 = require('./utils') */;
|
|||
|
|
|||
|
window.SimpleJekyllSearch = function (_options) {
|
|||
|
const errors = optionsValidator.validate(_options)
|
|||
|
if (errors.length > 0) {
|
|||
|
throwError('You must specify the following required options: ' + requiredOptions)
|
|||
|
}
|
|||
|
|
|||
|
options = _$utils_9.merge(options, _options)
|
|||
|
|
|||
|
_$Templater_7.setOptions({
|
|||
|
template: options.searchResultTemplate,
|
|||
|
middleware: options.templateMiddleware
|
|||
|
})
|
|||
|
|
|||
|
_$Repository_4.setOptions({
|
|||
|
fuzzy: options.fuzzy,
|
|||
|
limit: options.limit,
|
|||
|
sort: options.sortMiddleware,
|
|||
|
exclude: options.exclude
|
|||
|
})
|
|||
|
|
|||
|
if (_$utils_9.isJSON(options.json)) {
|
|||
|
initWithJSON(options.json)
|
|||
|
} else {
|
|||
|
initWithURL(options.json)
|
|||
|
}
|
|||
|
|
|||
|
const rv = {
|
|||
|
search: search
|
|||
|
}
|
|||
|
|
|||
|
typeof options.success === 'function' && options.success.call(rv)
|
|||
|
return rv
|
|||
|
}
|
|||
|
|
|||
|
function initWithJSON (json) {
|
|||
|
_$Repository_4.put(json)
|
|||
|
registerInput()
|
|||
|
}
|
|||
|
|
|||
|
function initWithURL (url) {
|
|||
|
_$JSONLoader_2.load(url, function (err, json) {
|
|||
|
if (err) {
|
|||
|
throwError('failed to get JSON (' + url + ')')
|
|||
|
}
|
|||
|
initWithJSON(json)
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function emptyResultsContainer () {
|
|||
|
options.resultsContainer.innerHTML = ''
|
|||
|
}
|
|||
|
|
|||
|
function appendToResultsContainer (text) {
|
|||
|
options.resultsContainer.innerHTML += text
|
|||
|
}
|
|||
|
|
|||
|
function registerInput () {
|
|||
|
options.searchInput.addEventListener('input', function (e) {
|
|||
|
if (isWhitelistedKey(e.which)) {
|
|||
|
emptyResultsContainer()
|
|||
|
debounce(function () { search(e.target.value) }, options.debounceTime)
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function search (query) {
|
|||
|
if (isValidQuery(query)) {
|
|||
|
emptyResultsContainer()
|
|||
|
render(_$Repository_4.search(query), query)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function render (results, query) {
|
|||
|
const len = results.length
|
|||
|
if (len === 0) {
|
|||
|
return appendToResultsContainer(options.noResultsText)
|
|||
|
}
|
|||
|
for (let i = 0; i < len; i++) {
|
|||
|
results[i].query = query
|
|||
|
appendToResultsContainer(_$Templater_7.compile(results[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isValidQuery (query) {
|
|||
|
return query && query.length > 0
|
|||
|
}
|
|||
|
|
|||
|
function isWhitelistedKey (key) {
|
|||
|
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
|
|||
|
}
|
|||
|
|
|||
|
function throwError (message) {
|
|||
|
throw new Error('SimpleJekyllSearch --- ' + message)
|
|||
|
}
|
|||
|
})(window)
|
|||
|
|
|||
|
}());
|
|||
|
</script>
|
|||
|
|
|||
|
<!-- Configuration -->
|
|||
|
<script>
|
|||
|
SimpleJekyllSearch({
|
|||
|
searchInput: document.getElementById('search-input'),
|
|||
|
resultsContainer: document.getElementById('results-container'),
|
|||
|
noResultsText: '<p>Aucun résultat!</p>',
|
|||
|
json: '/search.json',
|
|||
|
searchResultTemplate: '<li><a href="{url}">{date} {title}</a> (Création {create})</li>'
|
|||
|
})
|
|||
|
</script>
|
|||
|
|
|||
|
</div></div>
|
|||
|
|
|||
|
|
|||
|
<script>(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
function scrollToAnchor(anchor, duration, callback) {
|
|||
|
var $root = this;
|
|||
|
$root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
|
|||
|
window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
|
|||
|
callback && callback();
|
|||
|
});
|
|||
|
}
|
|||
|
$.fn.scrollToAnchor = scrollToAnchor;
|
|||
|
});
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
function affix(options) {
|
|||
|
var $root = this, $window = $(window), $scrollTarget, $scroll,
|
|||
|
offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
|
|||
|
rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
|
|||
|
hasInit = false, curState;
|
|||
|
|
|||
|
function setOptions(options) {
|
|||
|
var _options = options || {};
|
|||
|
_options.offsetBottom && (offsetBottom = _options.offsetBottom);
|
|||
|
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
|
|||
|
_options.scroll && (scroll = _options.scroll);
|
|||
|
_options.disabled !== undefined && (disabled = _options.disabled);
|
|||
|
$scrollTarget = $(scrollTarget);
|
|||
|
isOverallScroller = window.isOverallScroller($scrollTarget[0]);
|
|||
|
$scroll = $(scroll);
|
|||
|
}
|
|||
|
function preCalc() {
|
|||
|
top();
|
|||
|
rootHeight = $root.outerHeight();
|
|||
|
rootTop = $root.offset().top + (isOverallScroller ? 0 : $scrollTarget.scrollTop());
|
|||
|
rootLeft = $root.offset().left;
|
|||
|
}
|
|||
|
function calc(needPreCalc) {
|
|||
|
needPreCalc && preCalc();
|
|||
|
scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
|
|||
|
rootBottomTop = scrollBottom - rootTop;
|
|||
|
}
|
|||
|
function top() {
|
|||
|
if (curState !== 'top') {
|
|||
|
$root.removeClass('fixed').css({
|
|||
|
left: 0,
|
|||
|
top: 0
|
|||
|
});
|
|||
|
curState = 'top';
|
|||
|
}
|
|||
|
}
|
|||
|
function fixed() {
|
|||
|
if (curState !== 'fixed') {
|
|||
|
$root.addClass('fixed').css({
|
|||
|
left: rootLeft + 'px',
|
|||
|
top: 0
|
|||
|
});
|
|||
|
curState = 'fixed';
|
|||
|
}
|
|||
|
}
|
|||
|
function bottom() {
|
|||
|
if (curState !== 'bottom') {
|
|||
|
$root.removeClass('fixed').css({
|
|||
|
left: 0,
|
|||
|
top: rootBottomTop + 'px'
|
|||
|
});
|
|||
|
curState = 'bottom';
|
|||
|
}
|
|||
|
}
|
|||
|
function setState() {
|
|||
|
var scrollTop = $scrollTarget.scrollTop();
|
|||
|
if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
|
|||
|
fixed();
|
|||
|
} else if (scrollTop < rootTop) {
|
|||
|
top();
|
|||
|
} else {
|
|||
|
bottom();
|
|||
|
}
|
|||
|
}
|
|||
|
function init() {
|
|||
|
if(!hasInit) {
|
|||
|
var interval, timeout;
|
|||
|
calc(true); setState();
|
|||
|
// run calc every 100 millisecond
|
|||
|
interval = setInterval(function() {
|
|||
|
calc();
|
|||
|
}, 100);
|
|||
|
timeout = setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
}, 45000);
|
|||
|
window.pageLoad.then(function() {
|
|||
|
setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
clearTimeout(timeout);
|
|||
|
}, 3000);
|
|||
|
});
|
|||
|
$scrollTarget.on('scroll', function() {
|
|||
|
disabled || setState();
|
|||
|
});
|
|||
|
$window.on('resize', function() {
|
|||
|
disabled || (calc(true), setState());
|
|||
|
});
|
|||
|
hasInit = true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
setOptions(options);
|
|||
|
if (!disabled) {
|
|||
|
init();
|
|||
|
}
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
init();
|
|||
|
}, 200));
|
|||
|
return {
|
|||
|
setOptions: setOptions,
|
|||
|
refresh: function() {
|
|||
|
calc(true, { animation: false }); setState();
|
|||
|
}
|
|||
|
};
|
|||
|
}
|
|||
|
$.fn.affix = affix;
|
|||
|
});
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
function toc(options) {
|
|||
|
var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
|
|||
|
selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
|
|||
|
headingsPos, scrolling = false, hasRendered = false, hasInit = false;
|
|||
|
|
|||
|
function setOptions(options) {
|
|||
|
var _options = options || {};
|
|||
|
_options.selectors && (selectors = _options.selectors);
|
|||
|
_options.container && (container = _options.container);
|
|||
|
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
|
|||
|
_options.scroller && (scroller = _options.scroller);
|
|||
|
_options.disabled !== undefined && (disabled = _options.disabled);
|
|||
|
$headings = $(container).find(selectors).filter('[id]');
|
|||
|
$scrollTarget = $(scrollTarget);
|
|||
|
$scroller = $(scroller);
|
|||
|
}
|
|||
|
function calc() {
|
|||
|
headingsPos = [];
|
|||
|
$headings.each(function() {
|
|||
|
headingsPos.push(Math.floor($(this).position().top));
|
|||
|
});
|
|||
|
}
|
|||
|
function setState(element, disabled) {
|
|||
|
var scrollTop = $scrollTarget.scrollTop(), i;
|
|||
|
if (disabled || !headingsPos || headingsPos.length < 1) { return; }
|
|||
|
if (element) {
|
|||
|
$activeCur = element;
|
|||
|
} else {
|
|||
|
for (i = 0; i < headingsPos.length; i++) {
|
|||
|
if (scrollTop >= headingsPos[i]) {
|
|||
|
$activeCur = $tocLi.eq(i);
|
|||
|
} else {
|
|||
|
$activeCur || ($activeCur = $tocLi.eq(i));
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
$activeLast && $activeLast.removeClass('active');
|
|||
|
($activeLast = $activeCur).addClass('active');
|
|||
|
}
|
|||
|
function render() {
|
|||
|
if(!hasRendered) {
|
|||
|
$root.append($tocUl);
|
|||
|
$headings.each(function() {
|
|||
|
var $this = $(this);
|
|||
|
$tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
|
|||
|
.append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
|
|||
|
});
|
|||
|
$tocLi = $tocUl.children('li');
|
|||
|
$tocUl.on('click', 'a', function(e) {
|
|||
|
e.preventDefault();
|
|||
|
var $this = $(this);
|
|||
|
scrolling = true;
|
|||
|
setState($this.parent());
|
|||
|
$scroller.scrollToAnchor($this.attr('href'), 400, function() {
|
|||
|
scrolling = false;
|
|||
|
});
|
|||
|
});
|
|||
|
}
|
|||
|
hasRendered = true;
|
|||
|
}
|
|||
|
function init() {
|
|||
|
var interval, timeout;
|
|||
|
if(!hasInit) {
|
|||
|
render(); calc(); setState(null, scrolling);
|
|||
|
// run calc every 100 millisecond
|
|||
|
interval = setInterval(function() {
|
|||
|
calc();
|
|||
|
}, 100);
|
|||
|
timeout = setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
}, 45000);
|
|||
|
window.pageLoad.then(function() {
|
|||
|
setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
clearTimeout(timeout);
|
|||
|
}, 3000);
|
|||
|
});
|
|||
|
$scrollTarget.on('scroll', function() {
|
|||
|
disabled || setState(null, scrolling);
|
|||
|
});
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
if (!disabled) {
|
|||
|
render(); calc(); setState(null, scrolling);
|
|||
|
}
|
|||
|
}, 100));
|
|||
|
}
|
|||
|
hasInit = true;
|
|||
|
}
|
|||
|
|
|||
|
setOptions(options);
|
|||
|
if (!disabled) {
|
|||
|
init();
|
|||
|
}
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
init();
|
|||
|
}, 200));
|
|||
|
return {
|
|||
|
setOptions: setOptions
|
|||
|
};
|
|||
|
}
|
|||
|
$.fn.toc = toc;
|
|||
|
});
|
|||
|
})();
|
|||
|
/*(function () {
|
|||
|
|
|||
|
})();*/
|
|||
|
</script><script>
|
|||
|
/* toc must before affix, since affix need to konw toc' height. */(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
var $window = $(window);
|
|||
|
var $articleContent = $('.js-article-content');
|
|||
|
var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
|
|||
|
var toc;
|
|||
|
var tocDisabled = false;
|
|||
|
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
|
|||
|
var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;
|
|||
|
|
|||
|
function disabled() {
|
|||
|
return $col2.css('display') === 'none' || !hasToc;
|
|||
|
}
|
|||
|
|
|||
|
tocDisabled = disabled();
|
|||
|
|
|||
|
toc = $tocRoot.toc({
|
|||
|
selectors: TOC_SELECTOR,
|
|||
|
container: $articleContent,
|
|||
|
scrollTarget: hasSidebar ? '.js-page-main' : null,
|
|||
|
scroller: hasSidebar ? '.js-page-main' : null,
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
tocDisabled = disabled();
|
|||
|
toc && toc.setOptions({
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
}, 100));
|
|||
|
|
|||
|
});
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
var $window = $(window), $pageFooter = $('.js-page-footer');
|
|||
|
var $pageAside = $('.js-page-aside');
|
|||
|
var affix;
|
|||
|
var tocDisabled = false;
|
|||
|
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
|
|||
|
|
|||
|
affix = $pageAside.affix({
|
|||
|
offsetBottom: $pageFooter.outerHeight(),
|
|||
|
scrollTarget: hasSidebar ? '.js-page-main' : null,
|
|||
|
scroller: hasSidebar ? '.js-page-main' : null,
|
|||
|
scroll: hasSidebar ? $('.js-page-main').children() : null,
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
affix && affix.setOptions({
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
}, 100));
|
|||
|
|
|||
|
window.pageAsideAffix = affix;
|
|||
|
});
|
|||
|
})();
|
|||
|
</script><!---->
|
|||
|
|
|||
|
</div>
|
|||
|
<script>(function () {
|
|||
|
var $root = document.getElementsByClassName('root')[0];
|
|||
|
if (window.hasEvent('touchstart')) {
|
|||
|
$root.dataset.isTouch = true;
|
|||
|
document.addEventListener('touchstart', function(){}, false);
|
|||
|
}
|
|||
|
})();
|
|||
|
</script>
|
|||
|
</body>
|
|||
|
</html>
|
|||
|
|