cppcheck complains about some possible speed improvements which could be
[ntk/apt.git] / apt-pkg / contrib / netrc.cc
CommitLineData
592b7800
MV
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
3// $Id: netrc.c,v 1.38 2007-11-07 09:21:35 bagder Exp $
4/* ######################################################################
5
6 netrc file parser - returns the login and password of a give host in
7 a specified netrc-type file
8
9 Originally written by Daniel Stenberg, <daniel@haxx.se>, et al. and
10 placed into the Public Domain, do with it what you will.
11
12 ##################################################################### */
13 /*}}}*/
14
f1c081b6 15#include <apt-pkg/configuration.h>
01fc8930 16#include <apt-pkg/fileutl.h>
592b7800
MV
17#include <iostream>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <unistd.h>
22#include <pwd.h>
23
24#include "netrc.h"
25
26
27/* Get user and password from .netrc when given a machine name */
28
29enum {
30 NOTHING,
31 HOSTFOUND, /* the 'machine' keyword was found */
32 HOSTCOMPLETE, /* the machine name following the keyword was found too */
33 HOSTVALID, /* this is "our" machine! */
34 HOSTEND /* LAST enum */
35};
36
37/* make sure we have room for at least this size: */
38#define LOGINSIZE 64
39#define PASSWORDSIZE 64
40#define NETRC DOT_CHAR "netrc"
41
42/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
43int parsenetrc (char *host, char *login, char *password, char *netrcfile = NULL)
44{
45 FILE *file;
46 int retcode = 1;
47 int specific_login = (login[0] != 0);
48 char *home = NULL;
49 bool netrc_alloc = false;
50 int state = NOTHING;
51
52 char state_login = 0; /* Found a login keyword */
53 char state_password = 0; /* Found a password keyword */
54 int state_our_login = false; /* With specific_login,
55 found *our* login name */
56
57 if (!netrcfile) {
58 home = getenv ("HOME"); /* portable environment reader */
59
60 if (!home) {
61 struct passwd *pw;
62 pw = getpwuid (geteuid ());
63 if(pw)
64 home = pw->pw_dir;
65 }
66
67 if (!home)
68 return -1;
69
70 asprintf (&netrcfile, "%s%s%s", home, DIR_CHAR, NETRC);
71 if(!netrcfile)
72 return -1;
73 else
74 netrc_alloc = true;
75 }
76
77 file = fopen (netrcfile, "r");
78 if(file) {
79 char *tok;
80 char *tok_buf;
81 bool done = false;
82 char netrcbuffer[256];
83
84 while (!done && fgets(netrcbuffer, sizeof (netrcbuffer), file)) {
85 tok = strtok_r (netrcbuffer, " \t\n", &tok_buf);
86 while (!done && tok) {
87 if(login[0] && password[0]) {
88 done = true;
89 break;
90 }
91
92 switch(state) {
93 case NOTHING:
94 if (!strcasecmp ("machine", tok)) {
95 /* the next tok is the machine name, this is in itself the
96 delimiter that starts the stuff entered for this machine,
97 after this we need to search for 'login' and
98 'password'. */
99 state = HOSTFOUND;
100 }
101 break;
102 case HOSTFOUND:
278835da
MV
103 /* extended definition of a "machine" if we have a "/"
104 we match the start of the string (host.startswith(token) */
105 if ((strchr(host, '/') && strstr(host, tok) == host) ||
106 (!strcasecmp (host, tok))) {
592b7800
MV
107 /* and yes, this is our host! */
108 state = HOSTVALID;
109 retcode = 0; /* we did find our host */
110 }
111 else
112 /* not our host */
113 state = NOTHING;
114 break;
115 case HOSTVALID:
116 /* we are now parsing sub-keywords concerning "our" host */
117 if (state_login) {
118 if (specific_login)
119 state_our_login = !strcasecmp (login, tok);
120 else
121 strncpy (login, tok, LOGINSIZE - 1);
122 state_login = 0;
123 } else if (state_password) {
124 if (state_our_login || !specific_login)
125 strncpy (password, tok, PASSWORDSIZE - 1);
126 state_password = 0;
127 } else if (!strcasecmp ("login", tok))
128 state_login = 1;
129 else if (!strcasecmp ("password", tok))
130 state_password = 1;
131 else if(!strcasecmp ("machine", tok)) {
132 /* ok, there's machine here go => */
133 state = HOSTFOUND;
134 state_our_login = false;
135 }
136 break;
137 } /* switch (state) */
138
139 tok = strtok_r (NULL, " \t\n", &tok_buf);
140 } /* while(tok) */
141 } /* while fgets() */
142
143 fclose(file);
144 }
145
146 if (netrc_alloc)
147 free(netrcfile);
148
149 return retcode;
150}
151
152void maybe_add_auth (URI &Uri, string NetRCFile)
153{
f1c081b6 154 if (_config->FindB("Debug::Acquire::netrc", false) == true)
01fc8930
MV
155 std::clog << "maybe_add_auth: " << (string)Uri
156 << " " << NetRCFile << std::endl;
f1c081b6 157 if (Uri.Password.empty () == true || Uri.User.empty () == true)
592b7800
MV
158 {
159 if (NetRCFile.empty () == false)
160 {
161 char login[64] = "";
162 char password[64] = "";
fc3eb5b2 163 char *netrcfile = strdup(NetRCFile.c_str());
592b7800 164
01fc8930 165 // first check for a generic host based netrc entry
fc3eb5b2 166 char *host = strdup(Uri.Host.c_str());
01fc8930 167 if (host && parsenetrc (host, login, password, netrcfile) == 0)
592b7800 168 {
01fc8930
MV
169 if (_config->FindB("Debug::Acquire::netrc", false) == true)
170 std::clog << "host: " << host
171 << " user: " << login
172 << " pass-size: " << strlen(password)
173 << std::endl;
592b7800
MV
174 Uri.User = string (login);
175 Uri.Password = string (password);
fc3eb5b2
DK
176 free(netrcfile);
177 free(host);
01fc8930 178 return;
592b7800 179 }
fc3eb5b2 180 free(host);
592b7800 181
278835da
MV
182 // if host did not work, try Host+Path next, this will trigger
183 // a lookup uri.startswith(host) in the netrc file parser (because
184 // of the "/"
fc3eb5b2 185 char *hostpath = strdup(string(Uri.Host+Uri.Path).c_str());
01fc8930
MV
186 if (hostpath && parsenetrc (hostpath, login, password, netrcfile) == 0)
187 {
188 if (_config->FindB("Debug::Acquire::netrc", false) == true)
189 std::clog << "hostpath: " << hostpath
190 << " user: " << login
191 << " pass-size: " << strlen(password)
192 << std::endl;
193 Uri.User = string (login);
194 Uri.Password = string (password);
01fc8930 195 }
fc3eb5b2
DK
196 free(netrcfile);
197 free(hostpath);
592b7800
MV
198 }
199 }
200}
201
202#ifdef DEBUG
203int main(int argc, char* argv[])
204{
205 char login[64] = "";
206 char password[64] = "";
207
208 if(argc < 2)
209 return -1;
210
211 if(0 == parsenetrc (argv[1], login, password, argv[2])) {
212 printf("HOST: %s LOGIN: %s PASSWORD: %s\n", argv[1], login, password);
213 }
214}
215#endif