E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gsecret.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2018 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 // gsecret.cpp
19 //
20
21 #include "gdef.h"
22 #include "gsecret.h"
23 #include "gstr.h"
24 #include "gbase64.h"
25 #include "gxtext.h"
26 #include "gmd5.h"
27 #include "gassert.h"
28 #include <sstream>
29
30 GAuth::Secret::Secret()
31 {
32 G_ASSERT( !valid() ) ;
33 }
34
35 GAuth::Secret::Secret( const std::string & id ) :
36 m_id(id)
37 {
38 G_ASSERT( !valid() ) ;
39 }
40
41 GAuth::Secret::Secret( const std::string & secret , const std::string & type ,
42 const std::string & id , const std::string & context ) :
43 m_id(id) ,
44 m_context(context)
45 {
46 G_ASSERT( type == G::Str::lower(type) ) ;
47 std::string reason = check( secret , type , id ) ;
48 if( !reason.empty() )
49 throw Error( reason ) ;
50
51 if( type == "plain" )
52 {
53 m_key = G::Xtext::decode( secret ) ;
54 }
55 else if( type == "md5" && isDotted(secret) )
56 {
57 m_key = undotted( secret ) ;
58 m_mask_type = type ;
59 }
60 else
61 {
62 G_ASSERT( G::Base64::valid(secret) ) ;
63 m_key = G::Base64::decode( secret ) ;
64 m_mask_type = type ;
65 }
66 }
67
68 std::string GAuth::Secret::check( const std::string & secret , const std::string & type , const std::string & id )
69 {
70 if( secret.empty() )
71 return "empty shared key" ;
72 if( type.empty() || type != G::Str::lower(type) || !G::Str::isPrintableAscii(type) )
73 return "invalid encoding type" ;
74 if( id.empty() || !G::Xtext::valid(id) )
75 return "invalid id" ;
76 if( type == "plain" && !G::Xtext::valid(secret) )
77 return "invalid plain secret" ;
78 if( type == "md5" && !( isDotted(secret) || G::Base64::valid(secret) ) )
79 return "invalid encoding of md5 secret" ;
80 if( type != "md5" && type != "plain" && !G::Base64::valid(secret) )
81 return "invalid base64 encoding of secret" ;
82 return std::string() ;
83 }
84
85 GAuth::Secret GAuth::Secret::none( const std::string & id )
86 {
87 return Secret( id ) ;
88 }
89
90 GAuth::Secret GAuth::Secret::none()
91 {
92 return Secret() ;
93 }
94
95 bool GAuth::Secret::valid() const
96 {
97 return !m_key.empty() ;
98 }
99
100 std::string GAuth::Secret::key() const
101 {
102 if( !valid() ) throw Error() ;
103 return m_key ;
104 }
105
106 bool GAuth::Secret::masked() const
107 {
108 return !m_mask_type.empty() ;
109 }
110
111 std::string GAuth::Secret::id() const
112 {
113 if( !valid() ) throw Error() ;
114 return m_id ;
115 }
116
117 std::string GAuth::Secret::maskType() const
118 {
119 if( !valid() ) throw Error() ;
120 return m_mask_type ;
121 }
122
123 std::string GAuth::Secret::info( const std::string & id_in ) const
124 {
125 std::ostringstream ss ;
126 ss << (valid()?(masked()?maskType():std::string("plaintext")):std::string("missing")) << " secret" ;
127 std::string id_ = ( id_in.empty() && valid() ) ? m_id : id_in ;
128 if( !id_.empty() )
129 {
130 ss << " for [" << G::Str::printable(id_) << "]" ;
131 }
132 ss << m_context ; // eg. secrets-file line number
133 return ss.str() ;
134 }
135
136 bool GAuth::Secret::isDotted( const std::string & s )
137 {
138 return
139 s.length() >= 15U &&
140 s.find_first_not_of("0123456789.") == std::string::npos &&
141 G::Str::splitIntoFields(s,".").size() == 8U ;
142 }
143
144 std::string GAuth::Secret::undotted( const std::string & s )
145 {
146 G::StringArray decimals = G::Str::splitIntoFields( s , "." ) ; decimals.resize( 8U ) ;
147 std::string result ;
148 for( size_t i = 0U ; i < 8U ; i++ )
149 {
150 G::Md5::big_t n = 0U ;
151 for( std::string::iterator p = decimals[i].begin() ; p != decimals[i].end() ; ++p )
152 {
153 n *= 10U ;
154 n += ((*p)-'0') ;
155 }
156 for( int j = 0 ; j < 4 ; j++ )
157 {
158 unsigned char uc = ( n & 0xffU ) ;
159 n >>= 8 ;
160 result.push_back( static_cast<char>(uc) ) ;
161 }
162 }
163 return result ;
164 }
165
166 /// \file gsecret.cpp
G::Base64::valid
static bool valid(const std::string &)
Returns true if the string can be decoded without any strict errors.
Definition: gbase64.cpp:66
G::Str::printable
static std::string printable(const std::string &in, char escape= '\\')
Returns a printable represention of the given input string.
Definition: gstr.cpp:701
gmd5.h
G::Xtext::decode
static std::string decode(const std::string &)
Decodes the given string.
Definition: gxtext.cpp:107
G::StringArray
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:33
G::Base64::decode
static std::string decode(const std::string &, bool strict=false)
Decodes the given string.
Definition: gbase64.cpp:57
GAuth::Secret::key
std::string key() const
Returns the key. Throws if not valid().
Definition: gsecret.cpp:100
GAuth::Secret::valid
bool valid() const
Returns true if the secret is valid.
Definition: gsecret.cpp:95
gsecret.h
GAuth::Secret::check
static std::string check(const std::string &, const std::string &, const std::string &)
Does a non-throwing check of the constructor parameters, returning an error or the empty string...
Definition: gsecret.cpp:68
GAuth::Secret::info
std::string info(const std::string &id=std::string()) const
Returns information for logging, excluding anything sensitive.
Definition: gsecret.cpp:123
G::Str::lower
static std::string lower(const std::string &s)
Returns a copy of 's' in which all Latin-1 uppercase characters have been replaced by lowercase chara...
Definition: gstr.cpp:599
G::Xtext::valid
static bool valid(const std::string &)
Returns true if a valid encoding.
Definition: gxtext.cpp:72
gstr.h
gassert.h
GAuth::Secret::id
std::string id() const
Returns the associated identity. Throws if not valid().
Definition: gsecret.cpp:111
GAuth::Valid::valid
virtual bool valid() const =0
Returns true if a valid source of information.
gxtext.h
GAuth::Secret::Secret
Secret(const std::string &, const std::string &, const std::string &, const std::string &=std::string())
Constructor used by the SecretsFile class.
Definition: gsecret.cpp:41
GAuth::Secret::none
static Secret none()
Factory function that returns a secret that is not valid() and has an empty id(). ...
Definition: gsecret.cpp:90
G::Str::isPrintableAscii
static bool isPrintableAscii(const std::string &s)
Returns true if every character is a 7-bit, non-control character (ie.
Definition: gstr.cpp:282
gbase64.h
GAuth::Secret::masked
bool masked() const
Returns true if key() is masked.
Definition: gsecret.cpp:106
GAuth::Secret::maskType
std::string maskType() const
Returns the masking function name, such as "MD5", or the empty string if not masked().
Definition: gsecret.cpp:117
G::Str::splitIntoFields
static void splitIntoFields(const std::string &in, StringArray &out, const std::string &separators, char escape= '\0', bool remove_escapes=true)
Splits the string into fields.
Definition: gstr.cpp:975
GAuth::Secret
Encapsulates a shared secret from the secrets file plus the associated userid.
Definition: gsecret.h:42