nis-util
1.0.D108
|
00001 // 00002 // nis-util - NIS Administration Utilities 00003 // Copyright (C) 2002, 2008, 2009, 2011, 2012 Peter Miller 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation; either version 2 of the License, or (at 00008 // your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 // 00018 00019 #include <lib/ac/string.h> 00020 00021 #include <lib/rcstring/accumulator.h> 00022 #include <lib/space/netid.h> 00023 00024 00025 space_netid::~space_netid() 00026 { 00027 } 00028 00029 00030 space_netid::space_netid(const rcstring &a_filename) : 00031 space(a_filename), 00032 last_uid(-1) 00033 { 00034 // discard_comments(); can't, because of netid of the form "a.b#c" 00035 discard_blank_lines(); 00036 } 00037 00038 00039 space_netid::pointer 00040 space_netid::create(const rcstring &a_filename) 00041 { 00042 return pointer(new space_netid(a_filename)); 00043 } 00044 00045 00046 space_netid::record::pointer 00047 space_netid::get(void) 00048 { 00049 for (;;) 00050 { 00051 source_location line_locn; 00052 line_t line; 00053 if (!read_one_line(line_locn, line)) 00054 { 00055 last_uid = -1; 00056 return record::pointer(); 00057 } 00058 00059 // 00060 // Check that the record is in one of two valid formats. 00061 // 00062 // unix.<uid>@<domain> <uid>:<gid>,<gid>... 00063 // unix.<host>#<domain> 0:<host> 00064 // ^ 00065 // `-- conflicts with comments?!? 00066 // 00067 // In the first format, it isn't essential for the two <uid> 00068 // fields to be the same. This is becase in the case where we 00069 // are mapping a foreign ID into a local user, they probably 00070 // won't match. 00071 // 00072 // In the second format, it's hard to figure out what mapping a 00073 // foreign host's permissions to a local host's permissions means. 00074 // It certainly doesn't sound especially desirable. 00075 // 00076 if (line.size() < 2) 00077 { 00078 error 00079 ( 00080 line_locn, 00081 "too few fields (expeced 2, given %d)", 00082 (int)line.size() 00083 ); 00084 continue; 00085 } 00086 if (line.size() > 2) 00087 { 00088 error 00089 ( 00090 line_locn, 00091 "too many fields (expected 2, given %ld)", 00092 (long)line.size() 00093 ); 00094 } 00095 00096 // 00097 // Pull apart the first word. 00098 // 00099 // unix.{rec_id}@{rec_domain} 00100 // 00101 rcstring rec_uid1; 00102 rcstring rec_domain; 00103 bool host_rec = false; 00104 { 00105 rcstring first = line[0]; 00106 if (!first.starts_with("unix.")) 00107 { 00108 error 00109 ( 00110 line_locn, 00111 "netid name %s not valid, must start with \"unix.\"", 00112 line[0].quote_c().c_str() 00113 ); 00114 continue; 00115 } 00116 first = first.substr(5, first.size() - 5); 00117 00118 const char *at = strchr(first.c_str(), '@'); 00119 if (at) 00120 { 00121 rcstring first1(first.c_str(), at - first.c_str()); 00122 ++at; 00123 rcstring first2(at); 00124 long first1_bin = -1; 00125 if (!first1.to_long(first1_bin) || first1_bin < 0) 00126 { 00127 error 00128 ( 00129 line_locn, 00130 "netid name %s not valid, uid %s not valid", 00131 line[0].quote_c().c_str(), 00132 first1.quote_c().c_str() 00133 ); 00134 continue; 00135 } 00136 // normalise 00137 first1 = rcstring::format("%ld", first1_bin); 00138 00139 if (first1_bin < last_uid) 00140 { 00141 error(line_locn, "user id %ld out of order", first1_bin); 00142 explain_sequence_errors(); 00143 } 00144 last_uid = first1_bin; 00145 00146 rec_uid1 = first1; 00147 rec_domain = first2; 00148 } 00149 else 00150 { 00151 const char *hash = strchr(first.c_str(), '#'); 00152 if (!hash) 00153 { 00154 error 00155 ( 00156 line_locn, 00157 "netid name %s not valid", 00158 line[0].quote_c().c_str() 00159 ); 00160 continue; 00161 } 00162 host_rec = true; 00163 rcstring first1(first.c_str(), hash - first.c_str()); 00164 ++hash; 00165 rcstring first2(hash); 00166 00167 long first1_bin = -1; 00168 if (first1.to_long(first1_bin)) 00169 { 00170 error 00171 ( 00172 line_locn, 00173 "netid name %s not valid, host name %s not valid", 00174 line[0].quote_c().c_str(), 00175 first1.quote_c().c_str() 00176 ); 00177 } 00178 rec_uid1 = first1; 00179 rec_domain = first2; 00180 } 00181 } 00182 00183 // 00184 // Pull apart the second word. 00185 // 00186 // {uid}:{gid},{gid}... 00187 // 0:{host},{host},... 00188 // 00189 rcstring rec_uid2; 00190 record::gids_t rec_gids; 00191 { 00192 rcstring second = line[1]; 00193 const char *colon = strchr(second.c_str(), ':'); 00194 if (!colon) 00195 { 00196 error 00197 ( 00198 line_locn, 00199 "netid value %s not valid, no '@' or '#' separator", 00200 line[1].quote_c().c_str() 00201 ); 00202 continue; 00203 } 00204 rcstring second1(second.c_str(), colon - second.c_str()); 00205 long second1_bin = -1; 00206 if (!second1.to_long(second1_bin) || second1_bin < 0) 00207 { 00208 error 00209 ( 00210 line_locn, 00211 "netid value %s not valid, " 00212 "user id %s not a positive number", 00213 line[1].quote_c().c_str(), 00214 second1.quote_c().c_str() 00215 ); 00216 continue; 00217 } 00218 if (host_rec && second1_bin != 0) 00219 { 00220 error 00221 ( 00222 line_locn, 00223 "netid value %s not valid, user id must be \"0\", not %s", 00224 second.quote_c().c_str(), 00225 second1.quote_c().c_str() 00226 ); 00227 } 00228 second1 = rcstring::format("%ld", second1_bin); // normalise 00229 ++colon; 00230 rcstring second2(colon, second.c_str() + second.size() - colon); 00231 00232 rec_uid2 = second1; 00233 rec_gids = second2.break_up(",", false); 00234 bool gids_ok = true; 00235 for 00236 ( 00237 record::gids_t::iterator git = rec_gids.begin(); 00238 git != rec_gids.end(); 00239 ++git 00240 ) 00241 { 00242 long value = -1; 00243 if (!git->to_long(value) || value < 0) 00244 { 00245 if (!host_rec) 00246 { 00247 error 00248 ( 00249 line_locn, 00250 "netid value %s not valid, " 00251 "group id %s not a positive number", 00252 second.quote_c().c_str(), 00253 git->quote_c().c_str() 00254 ); 00255 gids_ok = false; 00256 } 00257 } 00258 else 00259 { 00260 if (host_rec) 00261 { 00262 error 00263 ( 00264 line_locn, 00265 "netid value %s not valid, host name %s not valid", 00266 second.quote_c().c_str(), 00267 git->quote_c().c_str() 00268 ); 00269 gids_ok = false; 00270 } 00271 else 00272 { 00273 // normalise 00274 *git = rcstring::format("%ld", value); 00275 } 00276 } 00277 } 00278 if (!gids_ok) 00279 continue; 00280 } 00281 00282 // 00283 // Got a record. 00284 // 00285 record::pointer rp = 00286 space_netid::record::create 00287 ( 00288 line_locn, 00289 rec_uid1, 00290 rec_domain, 00291 rec_uid2, 00292 rec_gids 00293 ); 00294 00295 // 00296 // check the line length 00297 // 00298 if (rp->representation().size() >= 512) 00299 { 00300 error 00301 ( 00302 rp->get_source_location(), 00303 "line too long (NIS limits records to 511 bytes)" 00304 ); 00305 } 00306 00307 // 00308 // report success 00309 // 00310 return rp; 00311 } 00312 } 00313 00314 00315 space_netid::record::~record() 00316 { 00317 } 00318 00319 00320 space_netid::record::record( 00321 const source_location &a_locn, 00322 const rcstring &a_uid1, 00323 const rcstring &a_domain, 00324 const rcstring &a_uid2, 00325 const gids_t &a_gids 00326 ) : 00327 locn(a_locn), 00328 uid1(a_uid1), 00329 domain(a_domain), 00330 uid2(a_uid2), 00331 gids(a_gids) 00332 { 00333 } 00334 00335 00336 space_netid::record::pointer 00337 space_netid::record::create(const source_location &a_locn, 00338 const rcstring &a_uid1, const rcstring &a_domain, const rcstring &a_uid2, 00339 const gids_t &a_gids) 00340 { 00341 return pointer(new record(a_locn, a_uid1, a_domain, a_uid2, a_gids)); 00342 } 00343 00344 00345 rcstring 00346 space_netid::record::name(void) 00347 const 00348 { 00349 long dummy; 00350 if (uid2 == "0" && !uid1.to_long(dummy)) 00351 return ("unix." + uid1 + "#" + domain); 00352 return ("unix." + uid1 + "@" + domain); 00353 } 00354 00355 00356 rcstring 00357 space_netid::record::representation(void) 00358 const 00359 { 00360 rcstring_accumulator acc; 00361 acc.push_back("unix."); 00362 acc.push_back(uid1); 00363 acc.push_back(is_host_kind() ? '#' : '@'); 00364 acc.push_back(domain); 00365 acc.push_back(' '); 00366 acc.push_back(uid2); 00367 acc.push_back(':'); 00368 for (gids_t::const_iterator it = gids.begin(); it != gids.end(); ++it) 00369 { 00370 if (it != gids.begin()) 00371 acc.push_back(','); 00372 acc.push_back(*it); 00373 } 00374 return acc.mkstr(); 00375 } 00376 00377 00378 bool 00379 space_netid::record::is_host_kind(void) 00380 const 00381 { 00382 long dummy; 00383 return !uid1.to_long(dummy); 00384 } 00385 00386 00387 void 00388 space_netid::record::append(const rcstring &arg) 00389 { 00390 for (gids_t::const_iterator it = gids.begin(); it != gids.end(); ++it) 00391 { 00392 if (*it == arg) 00393 return; 00394 } 00395 gids.push_back(arg); 00396 } 00397 00398 00399 // vim: set ts=8 sw=4 et :