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