- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gsecretsfile.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gsecretsfile.cpp
19 //
20
21 #include "gdef.h"
22 #include "gauth.h"
23 #include "gsecretsfile.h"
24 #include "gsecrets.h"
25 #include "groot.h"
26 #include "gxtext.h"
27 #include "gstr.h"
28 #include "gdatetime.h"
29 #include "gfile.h"
30 #include "gassert.h"
31 #include "gmemory.h"
32 #include <map>
33 #include <set>
34 #include <fstream>
35 #include <string>
36 #include <algorithm> // std::swap
37 #include <utility> // std::swap, std::pair
38 #include <sstream>
39
40 GAuth::SecretsFile::SecretsFile( const G::Path & path , bool auto_ , const std::string & debug_name ,
41 const std::string & server_type ) :
42 m_path(path) ,
43 m_auto(auto_) ,
44 m_debug_name(debug_name) ,
45 m_server_type(server_type) ,
46 m_file_time(0) ,
47 m_check_time(G::DateTime::now())
48 {
49 m_server_type = m_server_type.empty() ? std::string("server") : m_server_type ;
50 G_DEBUG( "GAuth::Secrets: " << m_debug_name << ": \"" << path << "\"" ) ;
51 m_valid = ! path.str().empty() ;
52 if( m_valid )
53 read( path ) ;
54 }
55
56 bool GAuth::SecretsFile::valid() const
57 {
58 return m_valid ;
59 }
60
61 void GAuth::SecretsFile::reread() const
62 {
63 (const_cast<SecretsFile*>(this))->reread(0) ;
64 }
65
66 void GAuth::SecretsFile::reread( int )
67 {
68 if( m_auto )
69 {
70 G::DateTime::EpochTime now = G::DateTime::now() ;
71 G_DEBUG( "GAuth::SecretsFile::reread: file time checked at " << m_check_time << ": now " << now ) ;
72 if( now != m_check_time ) // at most once a second
73 {
74 m_check_time = now ;
75 G::DateTime::EpochTime t = readFileTime( m_path ) ;
76 G_DEBUG( "GAuth::SecretsFile::reread: current file time " << t << ": saved file time " << m_file_time ) ;
77 if( t != m_file_time )
78 {
79 G_LOG_S( "GAuth::Secrets: re-reading secrets file: " << m_path ) ;
80 read( m_path ) ;
81 }
82 }
83 }
84 }
85
86 void GAuth::SecretsFile::read( const G::Path & path )
87 {
88 std::auto_ptr<std::ifstream> file ;
89 {
90 G::Root claim_root ;
91 file <<= new std::ifstream( path.str().c_str() ) ;
92 }
93 if( !file->good() )
94 {
95 std::ostringstream ss ;
96 ss << "reading \"" << path << "\" for " << m_debug_name << " secrets" ;
97 throw Secrets::OpenError( ss.str() ) ;
98 }
99 m_file_time = readFileTime( path ) ;
100
101 m_map.clear() ;
102 m_set.clear() ;
103 unsigned int count = read( *file.get() ) ;
104 count++ ; // avoid 'unused' warning
105 G_DEBUG( "GAuth::SecretsFile::read: processed " << (count-1) << " records" ) ;
106 }
107
108 G::DateTime::EpochTime GAuth::SecretsFile::readFileTime( const G::Path & path )
109 {
110 G::Root claim_root ;
111 return G::File::time( path ) ;
112 }
113
114 unsigned int GAuth::SecretsFile::read( std::istream & file )
115 {
116 unsigned int count = 0U ;
117 for( unsigned int line_number = 1U ; file.good() ; ++line_number )
118 {
119 std::string line = G::Str::readLineFrom( file ) ;
120 if( !file )
121 break ;
122
123 G::Str::trim( line , G::Str::ws() ) ;
124 if( !line.empty() && line.at(0U) != '#' )
125 {
126 G::StringArray word_array ;
127 G::Str::splitIntoTokens( line , word_array , " \t" ) ;
128 if( word_array.size() > 4U )
129 {
130 G_WARNING( "GAuth::SecretsFile::read: ignoring extra fields on line "
131 << line_number << " of secrets file" ) ;
132 }
133 if( word_array.size() >= 4U )
134 {
135 bool processed = process( word_array[0U] , word_array[1U] , word_array[2U] , word_array[3U] ) ;
136 G_DEBUG( "GAuth::SecretsFile::read: line #" << line_number << (processed?" used":" ignored") ) ;
137 if( processed )
138 count++ ;
139 }
140 else
141 {
142 G_WARNING( "GAuth::SecretsFile::read: ignoring line "
143 << line_number << " of secrets file: too few fields" ) ;
144 }
145 }
146 }
147 return count ;
148 }
149
150 bool GAuth::SecretsFile::process( std::string side , std::string mechanism , std::string id , std::string secret )
151 {
152 G::Str::toUpper( mechanism ) ;
153 G::Str::toUpper( side ) ;
154
155 // allow columns 1 and 2 to switch around
156 if( mechanism == G::Str::upper(m_server_type) || mechanism == "CLIENT" )
157 std::swap( mechanism , side ) ;
158
159 if( side == G::Str::upper(m_server_type) )
160 {
161 // server-side
162 std::string key = mechanism + ":" + id ;
163 std::string value = secret ;
164 m_map.insert( std::make_pair(key,value) ) ;
165 m_set.insert( mechanism ) ;
166 return true ;
167 }
168 else if( side == "CLIENT" )
169 {
170 // client-side -- no userid in the key since only one secret
171 std::string key = mechanism + " client" ;
172 std::string value = id + " " + secret ;
173 m_map.insert( std::make_pair(key,value) ) ;
174 return true ;
175 }
176 else
177 {
178 return false ;
179 }
180 }
181
182 GAuth::SecretsFile::~SecretsFile()
183 {
184 }
185
186 std::string GAuth::SecretsFile::id( const std::string & mechanism ) const
187 {
188 reread() ;
189 Map::const_iterator p = m_map.find( mechanism+" client" ) ;
190 std::string result ;
191 if( p != m_map.end() && (*p).second.find(" ") != std::string::npos )
192 result = G::Xtext::decode( (*p).second.substr(0U,(*p).second.find(" ")) ) ;
193 G_DEBUG( "GAuth::Secrets::id: " << m_debug_name << ": \"" << mechanism << "\"" ) ;
194 return result ;
195 }
196
197 std::string GAuth::SecretsFile::secret( const std::string & mechanism ) const
198 {
199 reread() ;
200 Map::const_iterator p = m_map.find( mechanism+" client" ) ;
201 if( p == m_map.end() || (*p).second.find(" ") == std::string::npos )
202 return std::string() ;
203 else
204 return G::Xtext::decode( (*p).second.substr((*p).second.find(" ")+1U) ) ;
205 }
206
207 std::string GAuth::SecretsFile::secret( const std::string & mechanism , const std::string & id ) const
208 {
209 reread() ;
210 Map::const_iterator p = m_map.find( mechanism+":"+G::Xtext::encode(id) ) ;
211 if( p == m_map.end() )
212 return std::string() ;
213 else
214 return G::Xtext::decode( (*p).second ) ;
215 }
216
217 std::string GAuth::SecretsFile::path() const
218 {
219 return m_path.str() ;
220 }
221
222 bool GAuth::SecretsFile::contains( const std::string & mechanism ) const
223 {
224 return m_set.find(mechanism) != m_set.end() ;
225 }
226
G::Path::str
std::string str() const
Returns the path string.
Definition: gpath.cpp:135
G_LOG_S
#define G_LOG_S(expr)
Definition: glog.h:103
G::DateTime::now
static EpochTime now()
Returns the current epoch time.
Definition: gdatetime.cpp:34
G::DateTime::EpochTime
std::time_t EpochTime
Definition: gdatetime.h:41
G::Xtext::decode
static std::string decode(const std::string &)
Decodes the given string.
Definition: gxtext.cpp:79
GAuth::SecretsFile::valid
bool valid() const
Definition: gsecretsfile.cpp:56
G::Xtext::encode
static std::string encode(const std::string &)
Encodes the given string.
Definition: gxtext.cpp:58
G::StringArray
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:44
G::Root
A class which acquires the process's special privileges on construction and releases them on destruct...
Definition: groot.h:49
G::Str::splitIntoTokens
static void splitIntoTokens(const std::string &in, Strings &out, const std::string &ws)
Splits the string into 'ws'-delimited tokens.
Definition: gstr.cpp:714
GAuth::SecretsFile::~SecretsFile
~SecretsFile()
Definition: gsecretsfile.cpp:182
GAuth::SecretsFile::secret
std::string secret(const std::string &mechanism) const
Definition: gsecretsfile.cpp:197
groot.h
GAuth::SecretsFile::id
std::string id(const std::string &mechanism) const
Definition: gsecretsfile.cpp:186
gsecretsfile.h
G::Str::trim
static void trim(std::string &s, const std::string &ws)
Trims both ends of s, taking off any of the 'ws' characters.
Definition: gstr.cpp:133
GAuth::SecretsFile::contains
bool contains(const std::string &mechanism) const
Definition: gsecretsfile.cpp:222
GAuth::SecretsFile
A implementation class used by GAuth::Secrets.
Definition: gsecretsfile.h:42
GAuth::SecretsFile::SecretsFile
SecretsFile(const G::Path &path, bool auto_, const std::string &name, const std::string &type)
Definition: gsecretsfile.cpp:40
gstr.h
gsecrets.h
gauth.h
gassert.h
G
Low-level classes.
GAuth::SecretsFile::path
std::string path() const
Definition: gsecretsfile.cpp:217
gfile.h
G::Str::upper
static std::string upper(const std::string &s)
Returns a copy of 's' in which all lowercase characters have been replaced by uppercase characters...
Definition: gstr.cpp:426
G::Str::readLineFrom
static std::string readLineFrom(std::istream &stream, const std::string &eol=std::string())
Reads a line from the stream using the given line terminator.
Definition: gstr.cpp:536
G_DEBUG
#define G_DEBUG(expr)
Definition: glog.h:95
gxtext.h
gdatetime.h
gmemory.h
G::Path
A Path object represents a file system path.
Definition: gpath.h:44
G::File::time
static time_type time(const Path &file)
Returns the file's timestamp.
Definition: gfile_unix.cpp:78
G::Str::ws
static std::string ws()
A convenience function returning standard whitespace characters.
Definition: gstr.cpp:829
G_WARNING
#define G_WARNING(expr)
Definition: glog.h:107
G::Str::toUpper
static void toUpper(std::string &s)
Replaces all lowercase characters in string 's' by uppercase characters.
Definition: gstr.cpp:422