ActiveDirectoryForRuby 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ == 0.1.8 2007-12-06
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
@@ -0,0 +1,168 @@
1
+ Copyright (c) 2007 Juan Gabriel Medina Marquez
2
+ Released under LGPL
3
+
4
+ GNU LESSER GENERAL PUBLIC LICENSE
5
+ Version 3, 29 June 2007
6
+
7
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
8
+ Everyone is permitted to copy and distribute verbatim copies
9
+ of this license document, but changing it is not allowed.
10
+
11
+
12
+ This version of the GNU Lesser General Public License incorporates
13
+ the terms and conditions of version 3 of the GNU General Public
14
+ License, supplemented by the additional permissions listed below.
15
+
16
+ 0. Additional Definitions.
17
+
18
+ As used herein, "this License" refers to version 3 of the GNU Lesser
19
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
20
+ General Public License.
21
+
22
+ "The Library" refers to a covered work governed by this License,
23
+ other than an Application or a Combined Work as defined below.
24
+
25
+ An "Application" is any work that makes use of an interface provided
26
+ by the Library, but which is not otherwise based on the Library.
27
+ Defining a subclass of a class defined by the Library is deemed a mode
28
+ of using an interface provided by the Library.
29
+
30
+ A "Combined Work" is a work produced by combining or linking an
31
+ Application with the Library. The particular version of the Library
32
+ with which the Combined Work was made is also called the "Linked
33
+ Version".
34
+
35
+ The "Minimal Corresponding Source" for a Combined Work means the
36
+ Corresponding Source for the Combined Work, excluding any source code
37
+ for portions of the Combined Work that, considered in isolation, are
38
+ based on the Application, and not on the Linked Version.
39
+
40
+ The "Corresponding Application Code" for a Combined Work means the
41
+ object code and/or source code for the Application, including any data
42
+ and utility programs needed for reproducing the Combined Work from the
43
+ Application, but excluding the System Libraries of the Combined Work.
44
+
45
+ 1. Exception to Section 3 of the GNU GPL.
46
+
47
+ You may convey a covered work under sections 3 and 4 of this License
48
+ without being bound by section 3 of the GNU GPL.
49
+
50
+ 2. Conveying Modified Versions.
51
+
52
+ If you modify a copy of the Library, and, in your modifications, a
53
+ facility refers to a function or data to be supplied by an Application
54
+ that uses the facility (other than as an argument passed when the
55
+ facility is invoked), then you may convey a copy of the modified
56
+ version:
57
+
58
+ a) under this License, provided that you make a good faith effort to
59
+ ensure that, in the event an Application does not supply the
60
+ function or data, the facility still operates, and performs
61
+ whatever part of its purpose remains meaningful, or
62
+
63
+ b) under the GNU GPL, with none of the additional permissions of
64
+ this License applicable to that copy.
65
+
66
+ 3. Object Code Incorporating Material from Library Header Files.
67
+
68
+ The object code form of an Application may incorporate material from
69
+ a header file that is part of the Library. You may convey such object
70
+ code under terms of your choice, provided that, if the incorporated
71
+ material is not limited to numerical parameters, data structure
72
+ layouts and accessors, or small macros, inline functions and templates
73
+ (ten or fewer lines in length), you do both of the following:
74
+
75
+ a) Give prominent notice with each copy of the object code that the
76
+ Library is used in it and that the Library and its use are
77
+ covered by this License.
78
+
79
+ b) Accompany the object code with a copy of the GNU GPL and this license
80
+ document.
81
+
82
+ 4. Combined Works.
83
+
84
+ You may convey a Combined Work under terms of your choice that,
85
+ taken together, effectively do not restrict modification of the
86
+ portions of the Library contained in the Combined Work and reverse
87
+ engineering for debugging such modifications, if you also do each of
88
+ the following:
89
+
90
+ a) Give prominent notice with each copy of the Combined Work that
91
+ the Library is used in it and that the Library and its use are
92
+ covered by this License.
93
+
94
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
95
+ document.
96
+
97
+ c) For a Combined Work that displays copyright notices during
98
+ execution, include the copyright notice for the Library among
99
+ these notices, as well as a reference directing the user to the
100
+ copies of the GNU GPL and this license document.
101
+
102
+ d) Do one of the following:
103
+
104
+ 0) Convey the Minimal Corresponding Source under the terms of this
105
+ License, and the Corresponding Application Code in a form
106
+ suitable for, and under terms that permit, the user to
107
+ recombine or relink the Application with a modified version of
108
+ the Linked Version to produce a modified Combined Work, in the
109
+ manner specified by section 6 of the GNU GPL for conveying
110
+ Corresponding Source.
111
+
112
+ 1) Use a suitable shared library mechanism for linking with the
113
+ Library. A suitable mechanism is one that (a) uses at run time
114
+ a copy of the Library already present on the user's computer
115
+ system, and (b) will operate properly with a modified version
116
+ of the Library that is interface-compatible with the Linked
117
+ Version.
118
+
119
+ e) Provide Installation Information, but only if you would otherwise
120
+ be required to provide such information under section 6 of the
121
+ GNU GPL, and only to the extent that such information is
122
+ necessary to install and execute a modified version of the
123
+ Combined Work produced by recombining or relinking the
124
+ Application with a modified version of the Linked Version. (If
125
+ you use option 4d0, the Installation Information must accompany
126
+ the Minimal Corresponding Source and Corresponding Application
127
+ Code. If you use option 4d1, you must provide the Installation
128
+ Information in the manner specified by section 6 of the GNU GPL
129
+ for conveying Corresponding Source.)
130
+
131
+ 5. Combined Libraries.
132
+
133
+ You may place library facilities that are a work based on the
134
+ Library side by side in a single library together with other library
135
+ facilities that are not Applications and are not covered by this
136
+ License, and convey such a combined library under terms of your
137
+ choice, if you do both of the following:
138
+
139
+ a) Accompany the combined library with a copy of the same work based
140
+ on the Library, uncombined with any other library facilities,
141
+ conveyed under the terms of this License.
142
+
143
+ b) Give prominent notice with the combined library that part of it
144
+ is a work based on the Library, and explaining where to find the
145
+ accompanying uncombined form of the same work.
146
+
147
+ 6. Revised Versions of the GNU Lesser General Public License.
148
+
149
+ The Free Software Foundation may publish revised and/or new versions
150
+ of the GNU Lesser General Public License from time to time. Such new
151
+ versions will be similar in spirit to the present version, but may
152
+ differ in detail to address new problems or concerns.
153
+
154
+ Each version is given a distinguishing version number. If the
155
+ Library as you received it specifies that a certain numbered version
156
+ of the GNU Lesser General Public License "or any later version"
157
+ applies to it, you have the option of following the terms and
158
+ conditions either of that published version or of any later version
159
+ published by the Free Software Foundation. If the Library as you
160
+ received it does not specify a version number of the GNU Lesser
161
+ General Public License, you may choose any version of the GNU Lesser
162
+ General Public License ever published by the Free Software Foundation.
163
+
164
+ If the Library as you received it specifies that a proxy can decide
165
+ whether future versions of the GNU Lesser General Public License shall
166
+ apply, that proxy's public statement of acceptance of any version is
167
+ permanent authorization for you to choose that version for the
168
+ Library.
@@ -0,0 +1,25 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ config/hoe.rb
7
+ config/requirements.rb
8
+ lib/ActiveDirectoryForRuby.rb
9
+ lib/ActiveDirectoryForRuby/version.rb
10
+ log/debug.log
11
+ script/destroy
12
+ script/generate
13
+ script/txt2html
14
+ setup.rb
15
+ tasks/deployment.rake
16
+ tasks/environment.rake
17
+ tasks/website.rake
18
+ test/test_ActiveDirectoryForRuby.rb
19
+ test/test_helper.rb
20
+ test/sample_config.yml
21
+ website/index.html
22
+ website/index.txt
23
+ website/javascripts/rounded_corners_lite.inc.js
24
+ website/stylesheets/screen.css
25
+ website/template.rhtml
@@ -0,0 +1,51 @@
1
+ #=ActiveDirectoryForRuby
2
+ #
3
+ # Allows easy bare minimum access to MS Windows Server's
4
+ # ActiveDirectory data and authentication
5
+ #
6
+ #=How To Use
7
+ #
8
+ # Just create an ActiveDirectoryForRuby object, and pass
9
+ # your YAML configuration file as follows:
10
+ #
11
+ # myconn = ActiveDirectoryForRuby::ActiveDirectoryForRuby.new('myconfig.yml')
12
+ #
13
+ # Then, you can authenticate a user like this:
14
+ #
15
+ # myconn.authenticate('user.name', 'somepass') # returns true/false
16
+ #
17
+ # And get a user's data with:
18
+ #
19
+ # myconn['user.name'].ldap_givenname # returns 'User'
20
+ #
21
+ #=Configuration File
22
+ #
23
+ # The format for the configuratio file is as follows:
24
+ #---
25
+ # # Server info, host ip or name, and port
26
+ # # which usually will be 389 for a common
27
+ # # MS Windows server
28
+ # server:
29
+ # host : intranet.nuclearplant.com
30
+ # port : 389
31
+ #
32
+ # # Administrator or authenticating login info
33
+ # # distinguished_name
34
+ # admin:
35
+ # distinguished_name : CN=Montgomery Burns,CN=Admins,DC=nuclearplant,DC=com
36
+ # user_name : NUKEPLANT\montgomery.burns
37
+ # password : burnsy
38
+ #
39
+ # # The user data base structure and
40
+ # # the field name containing user names
41
+ # # which is usually sAMAccountName
42
+ # search:
43
+ # base : OU=USA,DC=nuclearplant,DC=com
44
+ # field : sAMAccountName
45
+ #---
46
+ #
47
+ #=License
48
+ #
49
+ # Copyright (c) 2007 Juan Gabriel Medina Marquez
50
+ # Released under the GNU Lesser General Public License
51
+ #
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
@@ -0,0 +1,71 @@
1
+ require 'ActiveDirectoryForRuby/version'
2
+
3
+ AUTHOR = 'Juan Gabriel Medina Marquez' # can also be an array of Authors
4
+ EMAIL = "rha7.com@gmail.com"
5
+ DESCRIPTION = "Active Directory For Ruby"
6
+ GEM_NAME = 'ActiveDirectoryForRuby' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'ad4ruby' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+
11
+ @config_file = "~/.rubyforge/user-config.yml"
12
+ @config = nil
13
+ RUBYFORGE_USERNAME = "unknown"
14
+ def rubyforge_username
15
+ unless @config
16
+ begin
17
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
18
+ rescue
19
+ puts <<-EOS
20
+ ERROR: No rubyforge config file found: #{@config_file}
21
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
22
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
23
+ EOS
24
+ exit
25
+ end
26
+ end
27
+ RUBYFORGE_USERNAME.replace @config["username"]
28
+ end
29
+
30
+
31
+ REV = nil
32
+ # UNCOMMENT IF REQUIRED:
33
+ # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
34
+ VERS = ActiveDirectoryForRuby::VERSION::STRING + (REV ? ".#{REV}" : "")
35
+ RDOC_OPTS = ['--quiet', '--title', 'ActiveDirectoryForRuby documentation',
36
+ "--opname", "index.html",
37
+ "--line-numbers",
38
+ "--main", "README",
39
+ "--inline-source"]
40
+
41
+ class Hoe
42
+ def extra_deps
43
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
44
+ @extra_deps
45
+ end
46
+ end
47
+
48
+ # Generate all the Rake tasks
49
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
50
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
51
+ p.author = AUTHOR
52
+ p.description = DESCRIPTION
53
+ p.email = EMAIL
54
+ p.summary = DESCRIPTION
55
+ p.url = HOMEPATH
56
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
57
+ p.test_globs = ["test/**/test_*.rb"]
58
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
59
+
60
+ # == Optional
61
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
62
+ #p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
63
+
64
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
65
+
66
+ end
67
+
68
+ CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
69
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
70
+ hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
71
+ hoe.rsync_args = '-av --delete --ignore-errors'
@@ -0,0 +1,17 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
16
+
17
+ require 'ActiveDirectoryForRuby'
@@ -0,0 +1,145 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ require 'rubygems'
3
+ require 'yaml'
4
+ require 'erb'
5
+ require 'net/ldap'
6
+
7
+ module ActiveDirectoryForRuby
8
+ class ActiveDirectoryForRubyFields #:nodoc:
9
+ def initialize(data) #:nodoc:
10
+ @data = data
11
+ end
12
+
13
+ def method_missing(methodname) #:nodoc:
14
+ strMethodName = methodname.id2name
15
+ if strMethodName[0..4] != 'ldap_'
16
+ raise "Method missing [#{strMethodName}]"
17
+ return nil
18
+ end
19
+ symFieldName = strMethodName[5..99999].to_sym
20
+ data = @data[symFieldName]
21
+ data = data[0] if data.length == 1 if data.class == Array unless data.nil?
22
+ data = nil if data.length == 0 if data.class == Array unless data.nil?
23
+ return data
24
+ end
25
+ end
26
+
27
+ #=ActiveDirectoryForRuby
28
+ #
29
+ # Allows for easy access to MS Windows Server's ActiveDirectory
30
+ # Authentication and data.
31
+ #
32
+ # Overrides [] operator, maps LDAP fields to Method names, and provides
33
+ # a simple authenticate() method for easy authentication.
34
+ #
35
+ class ActiveDirectoryForRuby
36
+
37
+ #= Constructor
38
+ #
39
+ # Receives a single parameter which is the path to the
40
+ # ActiveDirectory data YAML config file.
41
+ #
42
+ # Config file's structure is describe in README.txt
43
+ #
44
+ def initialize(strConfigFile)
45
+ lconfig = YAML::load(ERB.new(IO.read(strConfigFile)).result).freeze
46
+ @config = {}
47
+ lconfig.each do |key, value|
48
+ temp = {}
49
+ value.each do |key2, value2|
50
+ temp[key2.to_sym] = value2
51
+ end
52
+ @config[key.to_sym] = temp
53
+ end
54
+ end
55
+
56
+ # Returns true or false depending on wether
57
+ # user and password were or not succesfully authenticated.
58
+ # example:
59
+ #
60
+ # adconn.authenticate('myuser', 'secretpass')
61
+ # => true
62
+ #
63
+ def authenticate(user, pass)
64
+ ldap_con = createconnection(@config[:admin][:distinguished_name], @config[:admin][:password])
65
+ user_filter = Net::LDAP::Filter.eq( @config[:search][:field], user )
66
+ op_filter = Net::LDAP::Filter.eq( "objectClass", "organizationalPerson" )
67
+ dn = String.new
68
+ ldap_con.search( :base => @config[:search][:base], :filter => op_filter & user_filter, :attributes=> 'dn') do |entry|
69
+ dn = entry.dn
70
+ end
71
+ login_succeeded = false
72
+ unless dn.empty?
73
+ ldap_con = createconnection(dn, pass)
74
+ login_succeeded = true if ldap_con.bind
75
+ end
76
+ return login_succeeded
77
+ end
78
+
79
+ # Receives a user's login and optionally a second parameter
80
+ # as an array containing symbols representing fields in LDAP
81
+ # examples:
82
+ #
83
+ # adconn.get('myuser') # Would return all fields
84
+ # win.get('myuser', [ :cn, :sn ]) # Would return :dn, :cn and :sn
85
+ #
86
+ # Additionally get() creates an additional field :organizational_unit
87
+ # based on :dn with a humanized version of any Organizational Unit (OU)
88
+ # fields available in :dn and reversed, for example if we had a :dn like
89
+ #
90
+ # 'CN=Homer Simpson,OU=Springfield,OU=USA,DC=nuclearplant,DC=com'
91
+ #
92
+ # win.get('myuser')[:organizational_unit]
93
+ #
94
+ # would yield: 'USA, Springfield'
95
+ #
96
+ def get(user, what = nil)
97
+ @data ||= {}
98
+ if @data[user].nil?
99
+ ldap_con = createconnection(@config[:admin][:distinguished_name], @config[:admin][:password])
100
+ user_filter = Net::LDAP::Filter.eq( @config[:search][:field], user )
101
+ op_filter = Net::LDAP::Filter.eq( "objectClass", "organizationalPerson" )
102
+ data = nil
103
+ ldap_con.search( :base => @config[:search][:base], :filter => op_filter & user_filter, :attributes=> what) do |entry|
104
+ data = entry
105
+ data[:organizational_unit] = ''
106
+ data[:organizational_unit] = entry[:dn][0].split(',').collect{|c| case c[0..1] when 'OU' then c else nil end}.compact.collect{|c| c.split('=')[1] }.reverse.join(', ') unless entry[:dn][0].nil? unless entry[:dn].nil? unless entry.nil?
107
+ end
108
+ @data[user] = data
109
+ end
110
+ return @data[user]
111
+ end
112
+
113
+ # Defines the [] operator, which allows easy access to fields for a user,
114
+ # for example:
115
+ #
116
+ # pp adconn['user.name']
117
+ #
118
+ # Would return an object whose methods correspond to LDAP fields, with a *ldap_* prefix
119
+ # for example:
120
+ #
121
+ # pp adconn['user.name'].ldap_givenname
122
+ #
123
+ # Would return the user's givenname, which usually is in AD, the user's first name.
124
+ #
125
+ def[](username)
126
+ return ActiveDirectoryForRubyFields.new(get(username))
127
+ end
128
+
129
+ private
130
+
131
+ def createconnection(dn, pass)
132
+ return Net::LDAP.new(
133
+ {
134
+ :host => @config[:server][:host],
135
+ :port => @config[:server][:port],
136
+ :auth => {
137
+ :method => :simple,
138
+ :username => dn,
139
+ :password => pass
140
+ }
141
+ }
142
+ )
143
+ end
144
+ end
145
+ end