]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/zone2ldap.cc
2 * PowerDNS BIND Zone to LDAP converter
3 * Copyright (C) 2003 Norbert Sendetzky
4 * Copyright (C) 2007 bert hubert
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2
8 * the Free Software Foundation
10 * Additionally, the license of this program contains a special
11 * exception which allows to distribute the program in binary form when
12 * it is linked against OpenSSL.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "arguments.hh"
34 #include "bindparserclasses.hh"
36 #include "dnsrecords.hh"
39 #include "zoneparser-tng.hh"
49 unsigned int g_domainid
;
53 map
<DNSName
,bool> g_objects
;
54 map
<string
, bool> g_entries
;
55 map
<DNSName
,bool> g_recorddata
;
56 map
<DNSName
, map
<string
, bool> > g_recordttl
;
58 static std::string
encode_non_ascii( const std::string
&input
) {
59 std::ostringstream out
;
61 for ( auto i
: input
) {
62 if ( (unsigned char)i
> 0x7F )
63 out
<< '\\' << int( (unsigned char)i
);
71 static void callback_simple( unsigned int domain_id
, const DNSName
&domain
, const string
&qtype
, const string
&content
, int ttl
)
75 if( ! domain
.isPartOf(g_zonename
) )
77 cerr
<< "Domain '" << domain
<< "'' not part of '" << g_zonename
<< "'"<< endl
;
81 host
= domain
.makeRelative(g_zonename
);
83 if( g_pdnsinfo
&& qtype
== "SOA" ) {
84 cout
<< "dn: ou=" << domain
<< "," << g_metadatadn
<< endl
;
85 cout
<< "changetype: add" << endl
;
86 cout
<< "objectclass: organizationalUnit" << endl
;
87 cout
<< "ou: " << domain
.toStringNoDot() << endl
;
91 std::string stripped
=stripDot(content
);
92 std::string rrvalue
= stripped
+ ((stripped
.empty() || stripped
[stripped
.size()-1]==' ') ? "." : "");
93 std::string dn
= "dc=";
94 if( host
.countLabels() ) { dn
+= host
.toStringNoDot() + ",dc="; }
95 dn
+= g_zonename
.toStringNoDot() + "," + g_basedn
;
96 cout
<< "dn: " << dn
<< endl
;
98 if( host
.countLabels() == 0 ) { host
= g_zonename
; }
102 g_entries
[dn
] = true;
103 g_recorddata
[domain
] = true;
105 cout
<< "changetype: add" << endl
;
106 cout
<< "objectclass: dnsdomain2" << endl
;
107 cout
<< "objectclass: domainrelatedobject" << endl
;
108 cout
<< "objectclass: PdnsRecordData" << endl
;
109 if( g_pdnsinfo
&& qtype
== "SOA" ) {
110 cout
<< "objectclass: PdnsDomain" << endl
;
111 cout
<< "PdnsDomainId: " << domain_id
<< endl
;
113 cout
<< "dc: " << host
.toStringNoDot() << endl
;
114 if( g_dnsttl
) { cout
<< "dnsttl: " << ttl
<< endl
; }
115 cout
<< "associateddomain: " << domain
.toStringNoDot() << endl
;
119 cout
<< "changetype: modify" << endl
;
120 if ( !g_recorddata
[domain
] ) {
121 g_recorddata
[domain
] = true;
122 cout
<< "add: objectClass" << endl
;
123 cout
<< "objectClass: PdnsRecordData" << endl
;
126 if ( !g_recordttl
.count( domain
) || !g_recordttl
[domain
].count( qtype
) ) {
127 g_recordttl
[domain
][qtype
] = true;
128 cout
<< "add: PdnsRecordTTL" << endl
;
129 cout
<< "PdnsRecordTTL: " << qtype
<< "|" << ttl
<< endl
;
132 cout
<< "add: " << qtype
<< "Record" << endl
;
134 cout
<< qtype
<< "Record: " << rrvalue
<< endl
<< endl
;
139 static void callback_tree( unsigned int domain_id
, const DNSName
&domain
, const string
&qtype
, const string
&content
, int ttl
)
144 vector
<string
> parts
;
146 stringtok( parts
, domain
.toStringNoDot(), "." );
147 if( parts
.empty() ) { return; }
149 for( i
= parts
.size() - 1; i
> 0; i
-- )
151 net
.prependRawLabel(parts
[i
]);
152 dn
= "dc=" + parts
[i
] + "," + dn
;
154 if( !g_objects
[net
] )
156 g_objects
[net
] = true;
158 cout
<< "dn: " << dn
<< g_basedn
<< endl
;
159 cout
<< "changetype: add" << endl
;
160 cout
<< "objectclass: dnsdomain2" << endl
;
161 cout
<< "objectclass: domainrelatedobject" << endl
;
162 cout
<< "dc: " << parts
[i
] << endl
;
163 cout
<< "associateddomain: " << net
.toStringNoDot() << endl
<< endl
;
168 if( g_pdnsinfo
&& qtype
== "SOA" ) {
169 cout
<< "dn: ou=" << domain
<< "," << g_metadatadn
<< endl
;
170 cout
<< "changetype: add" << endl
;
171 cout
<< "objectclass: organizationalUnit" << endl
;
172 cout
<< "ou: " << domain
.toStringNoDot() << endl
;
176 std::string stripped
=stripDot(content
);
177 std::string rrvalue
= stripped
+ ((stripped
.empty() || stripped
[stripped
.size()-1]==' ') ? "." : "");
178 cout
<< "dn: " << "dc=" << parts
[0] << "," << dn
<< g_basedn
<< endl
;
180 if( !g_objects
[domain
] )
182 g_objects
[domain
] = true;
183 g_recorddata
[domain
] = true;
185 cout
<< "changetype: add" << endl
;
186 cout
<< "objectclass: dnsdomain2" << endl
;
187 cout
<< "objectclass: domainrelatedobject" << endl
;
188 cout
<< "objectclass: PdnsRecordData" << endl
;
189 if( g_pdnsinfo
&& qtype
== "SOA" ) {
190 cout
<< "objectclass: PdnsDomain" << endl
;
191 cout
<< "PdnsDomainId: " << domain_id
<< endl
;
193 cout
<< "dc: " << parts
[0] << endl
;
194 if( g_dnsttl
) { cout
<< "dnsttl: " << ttl
<< endl
; }
195 cout
<< "associateddomain: " << domain
.toStringNoDot() << endl
;
199 cout
<< "changetype: modify" << endl
;
200 if( g_pdnsinfo
&& qtype
== "SOA" ) {
201 cout
<< "add: objectclass" << endl
;
202 cout
<< "objectclass: PdnsDomain" << endl
;
204 cout
<< "add: PdnsDomainId" << endl
;
205 cout
<< "PdnsDomainId: " << domain_id
<< endl
;
208 if ( !g_recorddata
[domain
] ) {
209 g_recorddata
[domain
] = true;
210 cout
<< "add: objectClass" << endl
;
211 cout
<< "objectClass: PdnsRecordData" << endl
;
214 if ( !g_recordttl
.count( domain
) || !g_recordttl
[domain
].count( qtype
) ) {
215 g_recordttl
[domain
][qtype
] = true;
216 cout
<< "add: PdnsRecordTTL" << endl
;
217 cout
<< "PdnsRecordTTL: " << qtype
<< "|" << ttl
<< endl
;
220 cout
<< "add: " << qtype
<< "Record" << endl
;
222 cout
<< qtype
<< "Record: " << rrvalue
<< endl
<< endl
;
227 int main( int argc
, char* argv
[] )
230 vector
<string
> parts
;
235 std::ios_base::sync_with_stdio( false );
237 args
.setCmd( "help", "Provide a helpful message" );
238 args
.setCmd( "version", "Print the version" );
239 args
.setSwitch( "verbose", "Verbose comments on operation" ) = "no";
240 args
.setSwitch( "resume", "Continue after errors" ) = "no";
241 args
.setSwitch( "dnsttl", "Add dnsttl attribute to every entry" ) = "no";
242 args
.setSwitch( "pdns-info", "Add the PDNS domain info attributes (this mandates setting --metadata-dn)" ) = "no";
243 args
.set( "named-conf", "Bind 8 named.conf to parse" ) = "";
244 args
.set( "zone-file", "Zone file to parse" ) = "";
245 args
.set( "zone-name", "Specify a zone name if zone is set" ) = "";
246 args
.set( "basedn", "Base DN to store objects below" ) = "ou=hosts,o=mycompany,c=de";
247 args
.set( "layout", "How to arrange entries in the directory (simple or as tree)" ) = "simple";
248 args
.set( "domainid", "Domain ID of the first domain found (incremented afterwards)" ) = "1";
249 args
.set( "metadata-dn", "DN under which to store the domain metadata" ) = "";
250 args
.set( "max-generate-steps", "Maximum number of $GENERATE steps when loading a zone from a file")="0";
251 args
.set( "max-include-depth", "Maximum nested $INCLUDE depth when loading a zone from a file")="20";
253 args
.parse( argc
, argv
);
255 if(args
.mustDo("version")) {
256 cerr
<<"zone2ldap "<<VERSION
<<endl
;
260 if( args
.mustDo( "help" ) )
262 cout
<< "Syntax:" << endl
<< endl
;
263 cout
<< args
.helpstring() << endl
;
269 cerr
<< "Syntax:" << endl
<< endl
;
270 cerr
<< args
.helpstring() << endl
;
274 g_basedn
= args
["basedn"];
275 g_dnsttl
= args
.mustDo( "dnsttl" );
276 typedef std::function
<void(unsigned int, const DNSName
&, const string
&, const string
&, int)> callback_t
;
277 callback_t callback
= callback_simple
;
278 if( args
["layout"] == "tree" )
280 callback
=callback_tree
;
283 if ( args
.mustDo( "pdns-info" ) ) {
285 if( args
["metadata-dn"].empty() ) {
286 cerr
<< "You must set --metadata-dn when using --pdns-info" << endl
;
289 g_metadatadn
= args
["metadata-dn"];
295 if ( !args
["domainid"].empty() )
296 pdns::checked_stoi_into(g_domainid
, args
["domainid"]);
300 if( !args
["named-conf"].empty() )
302 BP
.setVerbose( args
.mustDo( "verbose" ) );
303 BP
.parse( args
["named-conf"] );
304 // ZP.setDirectory( BP.getDirectory() );
305 const vector
<BindDomainInfo
> &domains
= BP
.getDomains();
307 for(const auto& i
: domains
)
309 if (i
.type
!= "primary" && i
.type
!= "secondary" && !i
.type
.empty() && i
.type
!= "master" && i
.type
!= "slave") {
310 cerr
<< " Warning! Skipping '" << i
.type
<< "' zone '" << i
.name
<< "'" << endl
;
315 if( i
.name
!= g_rootdnsname
&& i
.name
!= DNSName("localhost") && i
.name
!= DNSName("0.0.127.in-addr.arpa") )
317 cerr
<< "Parsing file: " << i
.filename
<< ", domain: " << i
.name
<< endl
;
319 ZoneParserTNG
zpt(i
.filename
, i
.name
, BP
.getDirectory());
320 zpt
.setMaxGenerateSteps(args
.asNum("max-generate-steps"));
321 zpt
.setMaxIncludes(args
.asNum("max-include-depth"));
322 DNSResourceRecord rr
;
324 callback(g_domainid
, rr
.qname
, rr
.qtype
.toString(), encode_non_ascii(rr
.content
), rr
.ttl
);
325 if( rr
.qtype
== QType::SOA
)
330 catch( PDNSException
&ae
)
332 cerr
<< "Fatal error: " << ae
.reason
<< endl
;
333 if( !args
.mustDo( "resume" ) )
342 if( args
["zone-file"].empty() || args
["zone-name"].empty() )
344 cerr
<< "Error: At least zone-file and zone-name are required" << endl
;
348 g_zonename
= DNSName(args
["zone-name"]);
349 ZoneParserTNG
zpt(args
["zone-file"], g_zonename
);
350 zpt
.setMaxGenerateSteps(args
.asNum("max-generate-steps"));
351 DNSResourceRecord rr
;
353 callback(g_domainid
, rr
.qname
, rr
.qtype
.toString(), encode_non_ascii(rr
.content
), rr
.ttl
);
354 if ( rr
.qtype
== QType::SOA
)
359 catch( PDNSException
&ae
)
361 cerr
<< "Fatal error: " << ae
.reason
<< endl
;
364 catch( std::exception
&e
)
366 cerr
<< "Died because of STL error: " << e
.what() << endl
;
371 cerr
<< "Died because of unknown exception" << endl
;